diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 0b8534b7c9..ec2953a161 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -1,7 +1,11 @@ reviews: + path_filters: + - "!app/config/specs/**" + - "!docs/examples/**" + - "!docs/references/**" + - "!docs/sdks/**" auto_review: base_branches: - main - 1.6.x - - 1.7.x - - feat-sites # temporary until merged to 1.7.x \ No newline at end of file + - 1.7.x \ No newline at end of file diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 0000000000..6d73787d00 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,120 @@ +name: Benchmark +concurrency: + group: '${{ github.workflow }}-${{ github.ref }}' + cancel-in-progress: true +env: + IMAGE: appwrite-dev + CACHE_KEY: 'appwrite-dev-${{ github.event.pull_request.head.sha }}' +'on': + - pull_request +jobs: + setup: + name: Setup & Build Appwrite Image + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build Appwrite + uses: docker/build-push-action@v6 + with: + context: . + push: false + tags: '${{ env.IMAGE }}' + load: true + cache-from: type=gha + cache-to: 'type=gha,mode=max' + outputs: 'type=docker,dest=/tmp/${{ env.IMAGE }}.tar' + build-args: | + DEBUG=false + TESTING=true + VERSION=dev + - name: Cache Docker Image + uses: actions/cache@v4 + with: + key: '${{ env.CACHE_KEY }}' + path: '/tmp/${{ env.IMAGE }}.tar' + benchmarking: + name: Benchmark + runs-on: ubuntu-latest + needs: setup + permissions: + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Load Cache + uses: actions/cache@v4 + with: + key: '${{ env.CACHE_KEY }}' + path: '/tmp/${{ env.IMAGE }}.tar' + fail-on-cache-miss: true + - name: Load and Start Appwrite + run: | + sed -i 's/traefik/localhost/g' .env + docker load --input /tmp/${{ env.IMAGE }}.tar + docker compose up -d + sleep 10 + - name: Install Oha + run: | + echo "deb [signed-by=/usr/share/keyrings/azlux-archive-keyring.gpg] http://packages.azlux.fr/debian/ stable main" | sudo tee /etc/apt/sources.list.d/azlux.list + sudo wget -O /usr/share/keyrings/azlux-archive-keyring.gpg https://azlux.fr/repo.gpg + sudo apt update + sudo apt install oha + - name: Benchmark PR + run: 'oha -z 180s http://localhost/v1/health/version -j > benchmark.json' + - name: Cleaning + run: docker compose down -v + - name: Installing latest version + run: | + rm docker-compose.yml + rm .env + curl https://appwrite.io/install/compose -o docker-compose.yml + curl https://appwrite.io/install/env -o .env + sed -i 's/_APP_OPTIONS_ABUSE=enabled/_APP_OPTIONS_ABUSE=disabled/g' .env + docker compose up -d + sleep 10 + - name: Benchmark Latest + run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json + - name: Prepare comment + run: | + echo '## :sparkles: Benchmark results' > benchmark.txt + echo ' ' >> benchmark.txt + echo "- Requests per second: $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt + echo "- Requests with 200 status code: $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt + echo "- P99 latency: $(jq -r '.latencyPercentiles.p99' benchmark.json )" >> benchmark.txt + echo " " >> benchmark.txt + echo " " >> benchmark.txt + echo "## :zap: Benchmark Comparison" >> benchmark.txt + echo " " >> benchmark.txt + echo "| Metric | This PR | Latest version | " >> benchmark.txt + echo "| --- | --- | --- | " >> benchmark.txt + echo "| RPS | $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.summary.requestsPerSec|tonumber|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt + echo "| 200 | $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt + echo "| P99 | $(jq -r '.latencyPercentiles.p99' benchmark.json ) | $(jq -r '.latencyPercentiles.p99' benchmark-latest.json ) | " >> benchmark.txt + - name: Save results + uses: actions/upload-artifact@v4 + if: '${{ !cancelled() }}' + with: + name: benchmark.json + path: benchmark.json + retention-days: 7 + - name: Find Comment + if: github.event.pull_request.head.repo.full_name == github.repository + uses: peter-evans/find-comment@v3 + id: fc + with: + issue-number: '${{ github.event.pull_request.number }}' + comment-author: 'github-actions[bot]' + body-includes: Benchmark results + - name: Comment on PR + if: github.event.pull_request.head.repo.full_name == github.repository + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: '${{ steps.fc.outputs.comment-id }}' + issue-number: '${{ github.event.pull_request.number }}' + body-path: benchmark.txt + edit-mode: replace diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 645d5cb560..dbf307f962 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -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 + appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug --exclude=devKeys e2e_shared_mode_test: name: E2E Shared Mode Service Test @@ -228,7 +228,8 @@ jobs: Webhooks, VCS, Messaging, - Migrations + Migrations, + Tokens ] tables-mode: [ 'Shared V1', @@ -275,86 +276,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 + appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug --exclude=devKeys - benchmarking: - name: Benchmark + e2e_dev_keys: + name: E2E Service Test (Dev Keys) runs-on: ubuntu-latest needs: setup - permissions: - pull-requests: write + strategy: + fail-fast: false steps: - - name: Checkout repository + - name: checkout uses: actions/checkout@v4 + - name: Load Cache uses: actions/cache@v4 with: key: ${{ env.CACHE_KEY }} path: /tmp/${{ env.IMAGE }}.tar fail-on-cache-miss: true + - name: Load and Start Appwrite run: | - sed -i 's/traefik/localhost/g' .env - docker load --input /tmp/${{ env.IMAGE }}.tar + docker load --input /tmp/${{ env.IMAGE }}.tar + sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env docker compose up -d - sleep 10 - - name: Install Oha + sleep 30 + + - name: Run Projects tests with dev keys in ${{ matrix.tables-mode }} table mode run: | - echo "deb [signed-by=/usr/share/keyrings/azlux-archive-keyring.gpg] http://packages.azlux.fr/debian/ stable main" | sudo tee /etc/apt/sources.list.d/azlux.list - sudo wget -O /usr/share/keyrings/azlux-archive-keyring.gpg https://azlux.fr/repo.gpg - sudo apt update - sudo apt install oha - - name: Benchmark PR - run: oha -z 180s http://localhost/v1/health/version -j > benchmark.json - - name: Cleaning - run: docker compose down -v - - name: Installing latest version + echo "Using project tables" + export _APP_DATABASE_SHARED_TABLES= + export _APP_DATABASE_SHARED_TABLES_V1= + + docker compose exec -T \ + -e _APP_DATABASE_SHARED_TABLES \ + -e _APP_DATABASE_SHARED_TABLES_V1 \ + appwrite test /usr/src/code/tests/e2e/Services/Projects --debug --group=devKeys + + e2e_dev_keys_shared_mode: + name: E2E Shared Mode Service Test (Dev Keys) + runs-on: ubuntu-latest + needs: [ setup, check_database_changes ] + if: needs.check_database_changes.outputs.database_changed == 'true' + strategy: + fail-fast: false + matrix: + tables-mode: [ + 'Shared V1', + 'Shared V2', + ] + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: Load Cache + uses: actions/cache@v4 + with: + key: ${{ env.CACHE_KEY }} + path: /tmp/${{ env.IMAGE }}.tar + fail-on-cache-miss: true + + - name: Load and Start Appwrite run: | - rm docker-compose.yml - rm .env - curl https://appwrite.io/install/compose -o docker-compose.yml - curl https://appwrite.io/install/env -o .env - sed -i 's/_APP_OPTIONS_ABUSE=enabled/_APP_OPTIONS_ABUSE=disabled/g' .env + docker load --input /tmp/${{ env.IMAGE }}.tar + sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env docker compose up -d - sleep 10 - - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json - - name: Prepare comment + sleep 30 + + - name: Run Projects tests with dev keys in ${{ matrix.tables-mode }} table mode run: | - echo '## :sparkles: Benchmark results' > benchmark.txt - echo ' ' >> benchmark.txt - echo "- Requests per second: $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt - echo "- Requests with 200 status code: $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt - echo "- P99 latency: $(jq -r '.latencyPercentiles.p99' benchmark.json )" >> benchmark.txt - echo " " >> benchmark.txt - echo " " >> benchmark.txt - echo "## :zap: Benchmark Comparison" >> benchmark.txt - echo " " >> benchmark.txt - echo "| Metric | This PR | Latest version | " >> benchmark.txt - echo "| --- | --- | --- | " >> benchmark.txt - echo "| RPS | $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.summary.requestsPerSec|tonumber|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt - echo "| 200 | $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt - echo "| P99 | $(jq -r '.latencyPercentiles.p99' benchmark.json ) | $(jq -r '.latencyPercentiles.p99' benchmark-latest.json ) | " >> benchmark.txt - - name: Save results - uses: actions/upload-artifact@v4 - if: ${{ !cancelled() }} - with: - name: benchmark.json - path: benchmark.json - retention-days: 7 - - name: Find Comment - if: github.event.pull_request.head.repo.full_name == github.repository - uses: peter-evans/find-comment@v3 - id: fc - with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: 'github-actions[bot]' - body-includes: Benchmark results - - name: Comment on PR - if: github.event.pull_request.head.repo.full_name == github.repository - uses: peter-evans/create-or-update-comment@v4 - with: - comment-id: ${{ steps.fc.outputs.comment-id }} - issue-number: ${{ github.event.pull_request.number }} - body-path: benchmark.txt - edit-mode: replace + if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then + echo "Using shared tables V1" + export _APP_DATABASE_SHARED_TABLES=database_db_main + export _APP_DATABASE_SHARED_TABLES_V1=database_db_main + elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then + echo "Using shared tables V2" + export _APP_DATABASE_SHARED_TABLES=database_db_main + export _APP_DATABASE_SHARED_TABLES_V1= + fi + + docker compose exec -T \ + -e _APP_DATABASE_SHARED_TABLES \ + -e _APP_DATABASE_SHARED_TABLES_V1 \ + appwrite test /usr/src/code/tests/e2e/Services/Projects --debug --group=devKeys diff --git a/app/config/collections/platform.php b/app/config/collections/platform.php index 6a26054636..ce8be6a874 100644 --- a/app/config/collections/platform.php +++ b/app/config/collections/platform.php @@ -287,6 +287,17 @@ return [ 'array' => false, 'filters' => ['subQueryKeys'], ], + [ + '$id' => ID::custom('devKeys'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryDevKeys'], + ], [ '$id' => ID::custom('search'), 'type' => Database::VAR_STRING, @@ -689,6 +700,125 @@ 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'), diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index ae27e81fcc..19547559e6 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -2402,4 +2402,77 @@ 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], + ], + + ], + ], ]; diff --git a/app/config/errors.php b/app/config/errors.php index 2c1bda995d..949b11e8d1 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -488,6 +488,18 @@ 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, diff --git a/app/config/roles.php b/app/config/roles.php index a4abee0c45..bccc2837f5 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -81,6 +81,8 @@ $admins = [ 'topics.read', 'subscribers.write', 'subscribers.read', + 'tokens.read', + 'tokens.write', ]; return [ diff --git a/app/config/scopes.php b/app/config/scopes.php index 41fee82a81..7dea7b1cd5 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -142,4 +142,10 @@ return [ // List of publicly visible scopes 'assistant.read' => [ 'description' => 'Access to read the Assistant service', ], + 'tokens.read' => [ + 'description' => 'Access to read your project\'s tokens', + ], + 'tokens.write' => [ + 'description' => 'Access to create, update, and delete your project\'s tokens', + ], ]; diff --git a/app/config/specs/open-api3-1.7.x-client.json b/app/config/specs/open-api3-1.7.x-client.json index b50c4ebf4c..1be340b5ec 100644 --- a/app/config/specs/open-api3-1.7.x-client.json +++ b/app/config/specs/open-api3-1.7.x-client.json @@ -4748,7 +4748,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -4763,7 +4763,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -4822,7 +4822,7 @@ "tags": [ "functions" ], - "description": "", + "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.", "responses": { "201": { "description": "Execution", @@ -4837,7 +4837,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -4936,7 +4936,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function execution log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -4951,7 +4951,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -5534,7 +5534,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -5616,7 +5616,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -7448,6 +7448,451 @@ } } } + }, + "\/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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": "" + }, + "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": "" + }, + "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": "" + }, + "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": "" + }, + "in": "path" + } + ] + } } }, "tags": [ @@ -7698,6 +8143,30 @@ "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", @@ -8894,6 +9363,50 @@ "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", diff --git a/app/config/specs/open-api3-1.7.x-console.json b/app/config/specs/open-api3-1.7.x-console.json index 019047436a..6c999d047a 100644 --- a/app/config/specs/open-api3-1.7.x-console.json +++ b/app/config/specs/open-api3-1.7.x-console.json @@ -4346,7 +4346,7 @@ "tags": [ "console" ], - "description": "", + "description": "Check if a resource ID is available.", "responses": { "204": { "description": "No content" @@ -4354,7 +4354,7 @@ }, "x-appwrite": { "method": "getResource", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -9036,7 +9036,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the project's functions. You can use the query params to filter your results.", "responses": { "200": { "description": "Functions List", @@ -9051,7 +9051,7 @@ }, "x-appwrite": { "method": "list", - "weight": 367, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -9108,7 +9108,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", "responses": { "201": { "description": "Function", @@ -9123,7 +9123,7 @@ }, "x-appwrite": { "method": "create", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -9338,7 +9338,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all runtimes that are currently active on your instance.", "responses": { "200": { "description": "Runtimes List", @@ -9353,7 +9353,7 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 369, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -9386,7 +9386,7 @@ "tags": [ "functions" ], - "description": "", + "description": "List allowed function specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -9401,7 +9401,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 370, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -9435,7 +9435,7 @@ "tags": [ "functions" ], - "description": "", + "description": "List available function templates. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", "responses": { "200": { "description": "Function Templates List", @@ -9450,7 +9450,7 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 393, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -9534,7 +9534,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function template using ID. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", "responses": { "200": { "description": "Template Function", @@ -9549,7 +9549,7 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -9593,7 +9593,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for all functions in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageFunctions", @@ -9608,7 +9608,7 @@ }, "x-appwrite": { "method": "listUsage", - "weight": 386, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -9664,7 +9664,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function by its unique ID.", "responses": { "200": { "description": "Function", @@ -9679,7 +9679,7 @@ }, "x-appwrite": { "method": "get", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -9722,7 +9722,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update function by its unique ID.", "responses": { "200": { "description": "Function", @@ -9737,7 +9737,7 @@ }, "x-appwrite": { "method": "update", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -9956,7 +9956,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a function by its unique ID.", "responses": { "204": { "description": "No content" @@ -9964,7 +9964,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 368, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -10009,7 +10009,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", "responses": { "200": { "description": "Function", @@ -10024,7 +10024,7 @@ }, "x-appwrite": { "method": "updateFunctionDeployment", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -10088,7 +10088,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the function's code deployments. You can use the query params to filter your results.", "responses": { "200": { "description": "Deployments List", @@ -10103,7 +10103,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -10170,7 +10170,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", "responses": { "202": { "description": "Deployment", @@ -10185,7 +10185,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 371, + "weight": 372, "cookies": false, "type": "upload", "deprecated": false, @@ -10265,7 +10265,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "202": { "description": "Deployment", @@ -10280,7 +10280,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 379, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -10349,7 +10349,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", "responses": { "202": { "description": "Deployment", @@ -10364,7 +10364,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -10451,7 +10451,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", "responses": { "202": { "description": "Deployment", @@ -10466,7 +10466,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -10547,7 +10547,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function deployment by its unique ID.", "responses": { "200": { "description": "Deployment", @@ -10562,7 +10562,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -10615,7 +10615,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a code deployment by its unique ID.", "responses": { "204": { "description": "No content" @@ -10623,7 +10623,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -10678,7 +10678,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", "responses": { "200": { "description": "File" @@ -10686,7 +10686,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 378, + "weight": 379, "cookies": false, "type": "location", "deprecated": false, @@ -10760,7 +10760,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Deployment", @@ -10775,7 +10775,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -10830,7 +10830,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -10845,7 +10845,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -10904,7 +10904,7 @@ "tags": [ "functions" ], - "description": "", + "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.", "responses": { "201": { "description": "Execution", @@ -10919,7 +10919,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -11018,7 +11018,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function execution log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -11033,7 +11033,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -11089,7 +11089,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a function execution by its unique ID.", "responses": { "204": { "description": "No content" @@ -11097,7 +11097,7 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -11152,7 +11152,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageFunction", @@ -11167,7 +11167,7 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11233,7 +11233,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all variables of a specific function.", "responses": { "200": { "description": "Variables List", @@ -11248,7 +11248,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11291,7 +11291,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", "responses": { "201": { "description": "Variable", @@ -11306,7 +11306,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -11381,7 +11381,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -11396,7 +11396,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -11449,7 +11449,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -11464,7 +11464,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11546,7 +11546,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a variable by its unique ID.", "responses": { "204": { "description": "No content" @@ -11554,7 +11554,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -13469,7 +13469,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -13544,7 +13544,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -13687,7 +13687,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -13832,7 +13832,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14005,7 +14005,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -14182,7 +14182,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -14290,7 +14290,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14401,7 +14401,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14453,7 +14453,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14514,7 +14514,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -14588,7 +14588,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14662,7 +14662,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -14737,7 +14737,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -14841,7 +14841,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -14948,7 +14948,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15032,7 +15032,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -15119,7 +15119,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 318, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -15233,7 +15233,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15350,7 +15350,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -15444,7 +15444,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -15541,7 +15541,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 319, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -15645,7 +15645,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -15752,7 +15752,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 320, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -15894,7 +15894,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -16038,7 +16038,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -16132,7 +16132,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16229,7 +16229,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -16323,7 +16323,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16420,7 +16420,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -16514,7 +16514,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16611,7 +16611,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16705,7 +16705,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16802,7 +16802,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -16854,7 +16854,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16915,7 +16915,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -16989,7 +16989,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17063,7 +17063,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -17136,7 +17136,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -17218,7 +17218,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -17277,7 +17277,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17353,7 +17353,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -17414,7 +17414,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -17488,7 +17488,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -17571,7 +17571,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -17660,7 +17660,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17722,7 +17722,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17796,7 +17796,7 @@ }, "x-appwrite": { "method": "list", - "weight": 310, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -17956,7 +17956,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 312, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -18026,6 +18026,84 @@ ] } }, + "\/migrations\/csv": { + "post": { + "summary": "Import documents from a CSV", + "operationId": "migrationsCreateCsvMigration", + "tags": [ + "migrations" + ], + "description": "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.", + "responses": { + "202": { + "description": "Migration", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migration" + } + } + } + } + }, + "x-appwrite": { + "method": "createCsvMigration", + "weight": 310, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-csv-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-csv.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "bucketId": { + "type": "string", + "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).", + "x-example": "" + }, + "fileId": { + "type": "string", + "description": "File ID.", + "x-example": "" + }, + "resourceId": { + "type": "string", + "description": "Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.", + "x-example": "[ID1:ID2]" + } + }, + "required": [ + "bucketId", + "fileId", + "resourceId" + ] + } + } + } + } + } + }, "\/migrations\/firebase": { "post": { "summary": "Migrate Firebase data", @@ -18123,7 +18201,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 313, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -18304,7 +18382,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 315, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -18540,7 +18618,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 314, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -18663,7 +18741,7 @@ }, "x-appwrite": { "method": "get", - "weight": 311, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -18720,7 +18798,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 316, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -18770,7 +18848,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 317, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -24101,7 +24179,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Create a new proxy rule for serving Appwrite's API on custom domain.", "responses": { "201": { "description": "Rule", @@ -24116,7 +24194,7 @@ }, "x-appwrite": { "method": "createAPIRule", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -24167,7 +24245,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Create a new proxy rule for executing Appwrite Function on custom domain.", "responses": { "201": { "description": "Rule", @@ -24182,7 +24260,7 @@ }, "x-appwrite": { "method": "createFunctionRule", - "weight": 426, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -24244,7 +24322,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Create a new proxy rule for to redirect from custom domain to another domain.", "responses": { "201": { "description": "Rule", @@ -24259,7 +24337,7 @@ }, "x-appwrite": { "method": "createRedirectRule", - "weight": 427, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -24335,7 +24413,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Create a new proxy rule for serving Appwrite Site on custom domain.", "responses": { "201": { "description": "Rule", @@ -24350,7 +24428,7 @@ }, "x-appwrite": { "method": "createSiteRule", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -24580,7 +24658,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all the project's sites. You can use the query params to filter your results.", "responses": { "200": { "description": "Sites List", @@ -24595,7 +24673,7 @@ }, "x-appwrite": { "method": "list", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -24649,7 +24727,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site.", "responses": { "201": { "description": "Site", @@ -24664,7 +24742,7 @@ }, "x-appwrite": { "method": "create", - "weight": 394, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -24894,7 +24972,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all frameworks that are currently available on the server instance.", "responses": { "200": { "description": "Frameworks List", @@ -24909,7 +24987,7 @@ }, "x-appwrite": { "method": "listFrameworks", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -24942,7 +25020,7 @@ "tags": [ "sites" ], - "description": "", + "description": "List allowed site specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -24957,7 +25035,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -24991,7 +25069,7 @@ "tags": [ "sites" ], - "description": "", + "description": "List available site templates. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", "responses": { "200": { "description": "Site Templates List", @@ -25006,7 +25084,7 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -25090,7 +25168,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site template using ID. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", "responses": { "200": { "description": "Template Site", @@ -25105,7 +25183,7 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -25149,7 +25227,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get usage metrics and statistics for all sites in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageSites", @@ -25164,7 +25242,7 @@ }, "x-appwrite": { "method": "listUsage", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -25220,7 +25298,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site by its unique ID.", "responses": { "200": { "description": "Site", @@ -25235,7 +25313,7 @@ }, "x-appwrite": { "method": "get", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -25278,7 +25356,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update site by its unique ID.", "responses": { "200": { "description": "Site", @@ -25293,7 +25371,7 @@ }, "x-appwrite": { "method": "update", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -25526,7 +25604,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site by its unique ID.", "responses": { "204": { "description": "No content" @@ -25534,7 +25612,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -25579,7 +25657,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", "responses": { "200": { "description": "Site", @@ -25594,7 +25672,7 @@ }, "x-appwrite": { "method": "updateSiteDeployment", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -25658,7 +25736,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all the site's code deployments. You can use the query params to filter your results.", "responses": { "200": { "description": "Deployments List", @@ -25673,7 +25751,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -25740,7 +25818,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", "responses": { "202": { "description": "Deployment", @@ -25755,7 +25833,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 400, + "weight": 401, "cookies": false, "type": "upload", "deprecated": false, @@ -25840,7 +25918,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "202": { "description": "Deployment", @@ -25855,7 +25933,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 408, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -25914,12 +25992,12 @@ }, "\/sites\/{siteId}\/deployments\/template": { "post": { - "summary": "Create deployment", + "summary": "Create template deployment", "operationId": "sitesCreateTemplateDeployment", "tags": [ "sites" ], - "description": "", + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", "responses": { "202": { "description": "Deployment", @@ -25934,7 +26012,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 401, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -26021,7 +26099,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", "responses": { "202": { "description": "Deployment", @@ -26036,7 +26114,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -26118,7 +26196,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site deployment by its unique ID.", "responses": { "200": { "description": "Deployment", @@ -26133,7 +26211,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -26186,7 +26264,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site deployment by its unique ID.", "responses": { "204": { "description": "No content" @@ -26194,7 +26272,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26249,7 +26327,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", "responses": { "200": { "description": "File" @@ -26257,7 +26335,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 407, + "weight": 408, "cookies": false, "type": "location", "deprecated": false, @@ -26331,7 +26409,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Cancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Deployment", @@ -26346,7 +26424,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -26401,7 +26479,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all site logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -26416,7 +26494,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -26471,7 +26549,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site request log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -26486,7 +26564,7 @@ }, "x-appwrite": { "method": "getLog", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -26539,7 +26617,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site log by its unique ID.", "responses": { "204": { "description": "No content" @@ -26547,7 +26625,7 @@ }, "x-appwrite": { "method": "deleteLog", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -26602,7 +26680,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get usage metrics and statistics for a for a specific site. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageSite", @@ -26617,7 +26695,7 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -26683,7 +26761,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all variables of a specific site.", "responses": { "200": { "description": "Variables List", @@ -26698,7 +26776,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 415, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -26741,7 +26819,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", "responses": { "201": { "description": "Variable", @@ -26756,7 +26834,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -26831,7 +26909,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -26846,7 +26924,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -26899,7 +26977,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -26914,7 +26992,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -26996,7 +27074,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a variable by its unique ID.", "responses": { "204": { "description": "No content" @@ -27004,7 +27082,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -29493,6 +29571,451 @@ } } }, + "\/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": [], + "Key": [], + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "File token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, "\/users": { "get": { "summary": "List users", @@ -33845,6 +34368,30 @@ "buckets" ] }, + "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", @@ -36724,6 +37271,50 @@ "antivirus" ] }, + "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", @@ -39911,6 +40502,18 @@ }, "x-example": [] }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, "builds": { "type": "array", "description": "Aggregated number of functions build per period.", @@ -39966,6 +40569,22 @@ "$ref": "#\/components\/schemas\/metric" }, "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] } }, "required": [ @@ -39983,13 +40602,17 @@ "functions", "deployments", "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", "builds", "buildsStorage", "buildsTime", "buildsMbSeconds", "executions", "executionsTime", - "executionsMbSeconds" + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" ] }, "usageFunction": { @@ -40019,6 +40642,18 @@ "x-example": 0, "format": "int32" }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, "buildsStorageTotal": { "type": "integer", "description": "total aggregated sum of function builds storage.", @@ -40031,6 +40666,12 @@ "x-example": 0, "format": "int32" }, + "buildsTimeAverage": { + "type": "integer", + "description": "Average builds compute time.", + "x-example": 0, + "format": "int32" + }, "buildsMbSecondsTotal": { "type": "integer", "description": "Total aggregated sum of function builds mbSeconds.", @@ -40126,6 +40767,269 @@ "$ref": "#\/components\/schemas\/metric" }, "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsSuccessTotal", + "buildsFailedTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsTimeAverage", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" + ] + }, + "usageSites": { + "description": "UsageSites", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of functions deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of functions deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of functions build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of functions build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of functions execution.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of functions deployment per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of functions deployment storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "builds": { + "type": "array", + "description": "Aggregated number of functions build per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of functions build storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of functions build compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of functions build mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of functions execution per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of functions execution compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of functions mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "sitesTotal": { + "type": "integer", + "description": "Total aggregated number of sites.", + "x-example": 0, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "Aggregated number of sites per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "requestsTotal": { + "type": "integer", + "description": "Total aggregated number of requests.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "inboundTotal": { + "type": "integer", + "description": "Total aggregated inbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "inbound": { + "type": "array", + "description": "Aggregated number of inbound bandwidth per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "outboundTotal": { + "type": "integer", + "description": "Total aggregated outbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "outbound": { + "type": "array", + "description": "Aggregated number of outbound bandwidth per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] } }, "required": [ @@ -40141,139 +41045,25 @@ "executionsMbSecondsTotal", "deployments", "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", "builds", "buildsStorage", "buildsTime", "buildsMbSeconds", "executions", "executionsTime", - "executionsMbSeconds" - ] - }, - "usageSites": { - "description": "UsageSites", - "type": "object", - "properties": { - "range": { - "type": "string", - "description": "Time range of the usage stats.", - "x-example": "30d" - }, - "sitesTotal": { - "type": "integer", - "description": "Total aggregated number of sites.", - "x-example": 0, - "format": "int32" - }, - "deploymentsTotal": { - "type": "integer", - "description": "Total aggregated number of sites deployments.", - "x-example": 0, - "format": "int32" - }, - "deploymentsStorageTotal": { - "type": "integer", - "description": "Total aggregated sum of sites deployment storage.", - "x-example": 0, - "format": "int32" - }, - "buildsTotal": { - "type": "integer", - "description": "Total aggregated number of sites build.", - "x-example": 0, - "format": "int32" - }, - "buildsStorageTotal": { - "type": "integer", - "description": "total aggregated sum of sites build storage.", - "x-example": 0, - "format": "int32" - }, - "buildsTimeTotal": { - "type": "integer", - "description": "Total aggregated sum of sites build compute time.", - "x-example": 0, - "format": "int32" - }, - "buildsMbSecondsTotal": { - "type": "integer", - "description": "Total aggregated sum of sites build mbSeconds.", - "x-example": 0, - "format": "int32" - }, - "sites": { - "type": "array", - "description": "Aggregated number of sites per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": 0 - }, - "deployments": { - "type": "array", - "description": "Aggregated number of sites deployment per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "deploymentsStorage": { - "type": "array", - "description": "Aggregated number of sites deployment storage per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "builds": { - "type": "array", - "description": "Aggregated number of sites build per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsStorage": { - "type": "array", - "description": "Aggregated sum of sites build storage per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsTime": { - "type": "array", - "description": "Aggregated sum of sites build compute time per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsMbSeconds": { - "type": "array", - "description": "Aggregated sum of sites build mbSeconds per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - } - }, - "required": [ - "range", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed", "sitesTotal", - "deploymentsTotal", - "deploymentsStorageTotal", - "buildsTotal", - "buildsStorageTotal", - "buildsTimeTotal", - "buildsMbSecondsTotal", "sites", - "deployments", - "deploymentsStorage", - "builds", - "buildsStorage", - "buildsTime", - "buildsMbSeconds" + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound" ] }, "usageSite": { @@ -40287,43 +41077,79 @@ }, "deploymentsTotal": { "type": "integer", - "description": "Total aggregated number of site deployments.", + "description": "Total aggregated number of function deployments.", "x-example": 0, "format": "int32" }, "deploymentsStorageTotal": { "type": "integer", - "description": "Total aggregated sum of site deployments storage.", + "description": "Total aggregated sum of function deployments storage.", "x-example": 0, "format": "int32" }, "buildsTotal": { "type": "integer", - "description": "Total aggregated number of site builds.", + "description": "Total aggregated number of function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", "x-example": 0, "format": "int32" }, "buildsStorageTotal": { "type": "integer", - "description": "total aggregated sum of site builds storage.", + "description": "total aggregated sum of function builds storage.", "x-example": 0, "format": "int32" }, "buildsTimeTotal": { "type": "integer", - "description": "Total aggregated sum of site builds compute time.", + "description": "Total aggregated sum of function builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeAverage": { + "type": "integer", + "description": "Average builds compute time.", "x-example": 0, "format": "int32" }, "buildsMbSecondsTotal": { "type": "integer", - "description": "Total aggregated sum of site builds mbSeconds.", + "description": "Total aggregated sum of function builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions mbSeconds.", "x-example": 0, "format": "int32" }, "deployments": { "type": "array", - "description": "Aggregated number of site deployments per period.", + "description": "Aggregated number of function deployments per period.", "items": { "$ref": "#\/components\/schemas\/metric" }, @@ -40331,7 +41157,7 @@ }, "deploymentsStorage": { "type": "array", - "description": "Aggregated number of site deployments storage per period.", + "description": "Aggregated number of function deployments storage per period.", "items": { "$ref": "#\/components\/schemas\/metric" }, @@ -40339,7 +41165,7 @@ }, "builds": { "type": "array", - "description": "Aggregated number of site builds per period.", + "description": "Aggregated number of function builds per period.", "items": { "$ref": "#\/components\/schemas\/metric" }, @@ -40347,7 +41173,7 @@ }, "buildsStorage": { "type": "array", - "description": "Aggregated sum of site builds storage per period.", + "description": "Aggregated sum of function builds storage per period.", "items": { "$ref": "#\/components\/schemas\/metric" }, @@ -40355,7 +41181,7 @@ }, "buildsTime": { "type": "array", - "description": "Aggregated sum of site builds compute time per period.", + "description": "Aggregated sum of function builds compute time per period.", "items": { "$ref": "#\/components\/schemas\/metric" }, @@ -40363,7 +41189,89 @@ }, "buildsMbSeconds": { "type": "array", - "description": "Aggregated number of site builds mbSeconds per period.", + "description": "Aggregated number of function builds mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of function executions per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of function executions compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of function mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "requestsTotal": { + "type": "integer", + "description": "Total aggregated number of requests.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "inboundTotal": { + "type": "integer", + "description": "Total aggregated inbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "inbound": { + "type": "array", + "description": "Aggregated number of inbound bandwidth per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "outboundTotal": { + "type": "integer", + "description": "Total aggregated outbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "outbound": { + "type": "array", + "description": "Aggregated number of outbound bandwidth per period.", "items": { "$ref": "#\/components\/schemas\/metric" }, @@ -40375,15 +41283,32 @@ "deploymentsTotal", "deploymentsStorageTotal", "buildsTotal", + "buildsSuccessTotal", + "buildsFailedTotal", "buildsStorageTotal", "buildsTimeTotal", + "buildsTimeAverage", "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", "deployments", "deploymentsStorage", "builds", "buildsStorage", "buildsTime", - "buildsMbSeconds" + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed", + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound" ] }, "usageProject": { @@ -40872,11 +41797,21 @@ "description": "Console Variables", "type": "object", "properties": { - "_APP_DOMAIN_TARGET": { + "_APP_DOMAIN_TARGET_CNAME": { "type": "string", "description": "CNAME target for your Appwrite custom domains.", "x-example": "appwrite.io" }, + "_APP_DOMAIN_TARGET_A": { + "type": "string", + "description": "A target for your Appwrite custom domains.", + "x-example": "127.0.0.1" + }, + "_APP_DOMAIN_TARGET_AAAA": { + "type": "string", + "description": "AAAA target for your Appwrite custom domains.", + "x-example": "::1" + }, "_APP_STORAGE_LIMIT": { "type": "integer", "description": "Maximum file size allowed for file upload in bytes.", @@ -40931,7 +41866,9 @@ } }, "required": [ - "_APP_DOMAIN_TARGET", + "_APP_DOMAIN_TARGET_CNAME", + "_APP_DOMAIN_TARGET_A", + "_APP_DOMAIN_TARGET_AAAA", "_APP_STORAGE_LIMIT", "_APP_COMPUTE_SIZE_LIMIT", "_APP_USAGE_STATS", @@ -41471,6 +42408,11 @@ "user" ] }, + "resourceId": { + "type": "string", + "description": "Id of the resource to migrate.", + "x-example": "databaseId:collectionId" + }, "statusCounters": { "type": "object", "description": "A group of counters that represent the total progress of the migration.", @@ -41499,6 +42441,7 @@ "source", "destination", "resources", + "resourceId", "statusCounters", "resourceData", "errors" diff --git a/app/config/specs/open-api3-1.7.x-server.json b/app/config/specs/open-api3-1.7.x-server.json index 9903453e60..ca30c5260e 100644 --- a/app/config/specs/open-api3-1.7.x-server.json +++ b/app/config/specs/open-api3-1.7.x-server.json @@ -8121,7 +8121,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the project's functions. You can use the query params to filter your results.", "responses": { "200": { "description": "Functions List", @@ -8136,7 +8136,7 @@ }, "x-appwrite": { "method": "list", - "weight": 367, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -8194,7 +8194,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", "responses": { "201": { "description": "Function", @@ -8209,7 +8209,7 @@ }, "x-appwrite": { "method": "create", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -8425,7 +8425,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all runtimes that are currently active on your instance.", "responses": { "200": { "description": "Runtimes List", @@ -8440,7 +8440,7 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 369, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -8474,7 +8474,7 @@ "tags": [ "functions" ], - "description": "", + "description": "List allowed function specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -8489,7 +8489,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 370, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -8524,7 +8524,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function by its unique ID.", "responses": { "200": { "description": "Function", @@ -8539,7 +8539,7 @@ }, "x-appwrite": { "method": "get", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -8583,7 +8583,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update function by its unique ID.", "responses": { "200": { "description": "Function", @@ -8598,7 +8598,7 @@ }, "x-appwrite": { "method": "update", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -8818,7 +8818,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a function by its unique ID.", "responses": { "204": { "description": "No content" @@ -8826,7 +8826,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 368, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -8872,7 +8872,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", "responses": { "200": { "description": "Function", @@ -8887,7 +8887,7 @@ }, "x-appwrite": { "method": "updateFunctionDeployment", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -8952,7 +8952,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the function's code deployments. You can use the query params to filter your results.", "responses": { "200": { "description": "Deployments List", @@ -8967,7 +8967,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9035,7 +9035,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", "responses": { "202": { "description": "Deployment", @@ -9050,7 +9050,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 371, + "weight": 372, "cookies": false, "type": "upload", "deprecated": false, @@ -9131,7 +9131,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "202": { "description": "Deployment", @@ -9146,7 +9146,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 379, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -9216,7 +9216,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", "responses": { "202": { "description": "Deployment", @@ -9231,7 +9231,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -9319,7 +9319,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", "responses": { "202": { "description": "Deployment", @@ -9334,7 +9334,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9416,7 +9416,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function deployment by its unique ID.", "responses": { "200": { "description": "Deployment", @@ -9431,7 +9431,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -9485,7 +9485,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a code deployment by its unique ID.", "responses": { "204": { "description": "No content" @@ -9493,7 +9493,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9549,7 +9549,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", "responses": { "200": { "description": "File" @@ -9557,7 +9557,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 378, + "weight": 379, "cookies": false, "type": "location", "deprecated": false, @@ -9632,7 +9632,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Deployment", @@ -9647,7 +9647,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -9703,7 +9703,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -9718,7 +9718,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -9779,7 +9779,7 @@ "tags": [ "functions" ], - "description": "", + "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.", "responses": { "201": { "description": "Execution", @@ -9794,7 +9794,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -9895,7 +9895,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function execution log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -9910,7 +9910,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -9968,7 +9968,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a function execution by its unique ID.", "responses": { "204": { "description": "No content" @@ -9976,7 +9976,7 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -10032,7 +10032,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all variables of a specific function.", "responses": { "200": { "description": "Variables List", @@ -10047,7 +10047,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10091,7 +10091,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", "responses": { "201": { "description": "Variable", @@ -10106,7 +10106,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -10182,7 +10182,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -10197,7 +10197,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -10251,7 +10251,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -10266,7 +10266,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -10349,7 +10349,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a variable by its unique ID.", "responses": { "204": { "description": "No content" @@ -10357,7 +10357,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -12316,7 +12316,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -12392,7 +12392,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -12536,7 +12536,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -12682,7 +12682,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -12856,7 +12856,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -13034,7 +13034,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -13143,7 +13143,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -13255,7 +13255,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -13308,7 +13308,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -13370,7 +13370,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -13445,7 +13445,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13520,7 +13520,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -13596,7 +13596,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -13701,7 +13701,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -13809,7 +13809,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -13894,7 +13894,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -13982,7 +13982,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 318, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -14097,7 +14097,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14215,7 +14215,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -14310,7 +14310,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -14408,7 +14408,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 319, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -14513,7 +14513,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -14621,7 +14621,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 320, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -14764,7 +14764,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -14909,7 +14909,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -15004,7 +15004,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -15102,7 +15102,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15197,7 +15197,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15295,7 +15295,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -15390,7 +15390,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -15488,7 +15488,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -15583,7 +15583,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -15681,7 +15681,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -15734,7 +15734,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -15796,7 +15796,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -15871,7 +15871,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -15946,7 +15946,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -16020,7 +16020,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -16103,7 +16103,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -16163,7 +16163,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16240,7 +16240,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16302,7 +16302,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -16377,7 +16377,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16461,7 +16461,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -16552,7 +16552,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -16615,7 +16615,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16676,7 +16676,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all the project's sites. You can use the query params to filter your results.", "responses": { "200": { "description": "Sites List", @@ -16691,7 +16691,7 @@ }, "x-appwrite": { "method": "list", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -16746,7 +16746,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site.", "responses": { "201": { "description": "Site", @@ -16761,7 +16761,7 @@ }, "x-appwrite": { "method": "create", - "weight": 394, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -16992,7 +16992,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all frameworks that are currently available on the server instance.", "responses": { "200": { "description": "Frameworks List", @@ -17007,7 +17007,7 @@ }, "x-appwrite": { "method": "listFrameworks", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -17041,7 +17041,7 @@ "tags": [ "sites" ], - "description": "", + "description": "List allowed site specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -17056,7 +17056,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -17091,7 +17091,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site by its unique ID.", "responses": { "200": { "description": "Site", @@ -17106,7 +17106,7 @@ }, "x-appwrite": { "method": "get", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -17150,7 +17150,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update site by its unique ID.", "responses": { "200": { "description": "Site", @@ -17165,7 +17165,7 @@ }, "x-appwrite": { "method": "update", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -17399,7 +17399,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site by its unique ID.", "responses": { "204": { "description": "No content" @@ -17407,7 +17407,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -17453,7 +17453,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", "responses": { "200": { "description": "Site", @@ -17468,7 +17468,7 @@ }, "x-appwrite": { "method": "updateSiteDeployment", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -17533,7 +17533,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all the site's code deployments. You can use the query params to filter your results.", "responses": { "200": { "description": "Deployments List", @@ -17548,7 +17548,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17616,7 +17616,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", "responses": { "202": { "description": "Deployment", @@ -17631,7 +17631,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 400, + "weight": 401, "cookies": false, "type": "upload", "deprecated": false, @@ -17717,7 +17717,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "202": { "description": "Deployment", @@ -17732,7 +17732,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 408, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -17792,12 +17792,12 @@ }, "\/sites\/{siteId}\/deployments\/template": { "post": { - "summary": "Create deployment", + "summary": "Create template deployment", "operationId": "sitesCreateTemplateDeployment", "tags": [ "sites" ], - "description": "", + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", "responses": { "202": { "description": "Deployment", @@ -17812,7 +17812,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 401, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -17900,7 +17900,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", "responses": { "202": { "description": "Deployment", @@ -17915,7 +17915,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -17998,7 +17998,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site deployment by its unique ID.", "responses": { "200": { "description": "Deployment", @@ -18013,7 +18013,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -18067,7 +18067,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site deployment by its unique ID.", "responses": { "204": { "description": "No content" @@ -18075,7 +18075,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -18131,7 +18131,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", "responses": { "200": { "description": "File" @@ -18139,7 +18139,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 407, + "weight": 408, "cookies": false, "type": "location", "deprecated": false, @@ -18214,7 +18214,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Cancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Deployment", @@ -18229,7 +18229,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -18285,7 +18285,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all site logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -18300,7 +18300,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18356,7 +18356,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site request log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -18371,7 +18371,7 @@ }, "x-appwrite": { "method": "getLog", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -18425,7 +18425,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site log by its unique ID.", "responses": { "204": { "description": "No content" @@ -18433,7 +18433,7 @@ }, "x-appwrite": { "method": "deleteLog", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -18489,7 +18489,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all variables of a specific site.", "responses": { "200": { "description": "Variables List", @@ -18504,7 +18504,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 415, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -18548,7 +18548,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", "responses": { "201": { "description": "Variable", @@ -18563,7 +18563,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -18639,7 +18639,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -18654,7 +18654,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18708,7 +18708,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -18723,7 +18723,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -18806,7 +18806,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a variable by its unique ID.", "responses": { "204": { "description": "No content" @@ -18814,7 +18814,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -21127,6 +21127,463 @@ } } }, + "\/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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "File token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, "\/users": { "get": { "summary": "List users", @@ -24706,6 +25163,30 @@ "buckets" ] }, + "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", @@ -27273,6 +27754,50 @@ "antivirus" ] }, + "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", diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 6d50b1e06e..4809b8f4fa 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -4763,7 +4763,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 384, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -4837,7 +4837,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 382, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -4951,7 +4951,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 383, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -7448,6 +7448,451 @@ } } } + }, + "\/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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": "" + }, + "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": "" + }, + "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": "" + }, + "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": "" + }, + "in": "path" + } + ] + } } }, "tags": [ @@ -7698,6 +8143,30 @@ "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", @@ -8894,6 +9363,50 @@ "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", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index a1f9e94f6c..371ca4aef0 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -4354,7 +4354,7 @@ }, "x-appwrite": { "method": "getResource", - "weight": 424, + "weight": 429, "cookies": false, "type": "", "deprecated": false, @@ -9051,7 +9051,7 @@ }, "x-appwrite": { "method": "list", - "weight": 368, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -9123,7 +9123,7 @@ }, "x-appwrite": { "method": "create", - "weight": 365, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -9353,7 +9353,7 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 370, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9401,7 +9401,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 371, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9450,7 +9450,7 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 394, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -9549,7 +9549,7 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 393, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -9608,7 +9608,7 @@ }, "x-appwrite": { "method": "listUsage", - "weight": 387, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -9679,7 +9679,7 @@ }, "x-appwrite": { "method": "get", - "weight": 366, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -9737,7 +9737,7 @@ }, "x-appwrite": { "method": "update", - "weight": 367, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -9964,7 +9964,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 369, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -10024,7 +10024,7 @@ }, "x-appwrite": { "method": "updateFunctionDeployment", - "weight": 374, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -10103,7 +10103,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 375, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -10185,7 +10185,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 372, + "weight": 377, "cookies": false, "type": "upload", "deprecated": false, @@ -10280,7 +10280,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 380, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -10364,7 +10364,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 377, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -10466,7 +10466,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 378, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10562,7 +10562,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 373, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -10623,7 +10623,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 376, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -10686,7 +10686,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 379, + "weight": 384, "cookies": false, "type": "location", "deprecated": false, @@ -10775,7 +10775,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 381, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -10845,7 +10845,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 384, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -10919,7 +10919,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 382, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -11033,7 +11033,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 383, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -11097,7 +11097,7 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 385, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11167,7 +11167,7 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 386, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11248,7 +11248,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 390, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -11306,7 +11306,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 388, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -11396,7 +11396,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 389, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -11464,7 +11464,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 391, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -11554,7 +11554,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 392, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -20708,6 +20708,389 @@ } } }, + "\/projects\/{projectId}\/dev-keys": { + "get": { + "summary": "List dev keys", + "operationId": "projectsListDevKeys", + "tags": [ + "projects" + ], + "description": "List all the project\\'s dev keys. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.'", + "responses": { + "200": { + "description": "Dev Keys List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/devKeyList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDevKeys", + "weight": 368, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-dev-keys.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the project\\'s dev keys. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.'", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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: accessedAt, expire", + "required": false, + "schema": { + "type": "string", + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create dev key", + "operationId": "projectsCreateDevKey", + "tags": [ + "projects" + ], + "description": "Create a new project dev key. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development. Strictly meant for development purposes only.", + "responses": { + "201": { + "description": "DevKey", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/devKey" + } + } + } + } + }, + "x-appwrite": { + "method": "createDevKey", + "weight": 365, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new project dev key. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development. Strictly meant for development purposes only.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format.", + "x-example": null + } + }, + "required": [ + "name", + "expire" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/dev-keys\/{keyId}": { + "get": { + "summary": "Get dev key", + "operationId": "projectsGetDevKey", + "tags": [ + "projects" + ], + "description": "Get a project\\'s dev key by its unique ID. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.", + "responses": { + "200": { + "description": "DevKey", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/devKey" + } + } + } + } + }, + "x-appwrite": { + "method": "getDevKey", + "weight": 367, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a project\\'s dev key by its unique ID. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update dev key", + "operationId": "projectsUpdateDevKey", + "tags": [ + "projects" + ], + "description": "Update a project\\'s dev key by its unique ID. Use this endpoint to update a project\\'s dev key name or expiration time.'", + "responses": { + "200": { + "description": "DevKey", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/devKey" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDevKey", + "weight": 366, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a project\\'s dev key by its unique ID. Use this endpoint to update a project\\'s dev key name or expiration time.'", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format.", + "x-example": null + } + }, + "required": [ + "name", + "expire" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete dev key", + "operationId": "projectsDeleteDevKey", + "tags": [ + "projects" + ], + "description": "Delete a project\\'s dev key by its unique ID. Once deleted, the key will no longer allow bypassing of rate limits and better logging of errors.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDevKey", + "weight": 369, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a project\\'s dev key by its unique ID. Once deleted, the key will no longer allow bypassing of rate limits and better logging of errors.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, "\/projects\/{projectId}\/jwts": { "post": { "summary": "Create JWT", @@ -24194,7 +24577,7 @@ }, "x-appwrite": { "method": "createAPIRule", - "weight": 425, + "weight": 430, "cookies": false, "type": "", "deprecated": false, @@ -24260,7 +24643,7 @@ }, "x-appwrite": { "method": "createFunctionRule", - "weight": 427, + "weight": 432, "cookies": false, "type": "", "deprecated": false, @@ -24337,7 +24720,7 @@ }, "x-appwrite": { "method": "createRedirectRule", - "weight": 428, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -24428,7 +24811,7 @@ }, "x-appwrite": { "method": "createSiteRule", - "weight": 426, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -24673,7 +25056,7 @@ }, "x-appwrite": { "method": "list", - "weight": 397, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -24742,7 +25125,7 @@ }, "x-appwrite": { "method": "create", - "weight": 395, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -24987,7 +25370,7 @@ }, "x-appwrite": { "method": "listFrameworks", - "weight": 400, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -25035,7 +25418,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 423, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -25084,7 +25467,7 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 419, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -25183,7 +25566,7 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 420, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -25242,7 +25625,7 @@ }, "x-appwrite": { "method": "listUsage", - "weight": 421, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -25313,7 +25696,7 @@ }, "x-appwrite": { "method": "get", - "weight": 396, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -25371,7 +25754,7 @@ }, "x-appwrite": { "method": "update", - "weight": 398, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -25612,7 +25995,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 399, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -25672,7 +26055,7 @@ }, "x-appwrite": { "method": "updateSiteDeployment", - "weight": 406, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -25751,7 +26134,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 405, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -25833,7 +26216,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 401, + "weight": 406, "cookies": false, "type": "upload", "deprecated": false, @@ -25933,7 +26316,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 409, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -26012,7 +26395,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 402, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26114,7 +26497,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 403, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -26211,7 +26594,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 404, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -26272,7 +26655,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 407, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -26335,7 +26718,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 408, + "weight": 413, "cookies": false, "type": "location", "deprecated": false, @@ -26424,7 +26807,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 410, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -26494,7 +26877,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 412, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -26564,7 +26947,7 @@ }, "x-appwrite": { "method": "getLog", - "weight": 411, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -26625,7 +27008,7 @@ }, "x-appwrite": { "method": "deleteLog", - "weight": 413, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -26695,7 +27078,7 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 422, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -26776,7 +27159,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 416, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -26834,7 +27217,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 414, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -26924,7 +27307,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 415, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -26992,7 +27375,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 417, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -27082,7 +27465,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 418, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -29571,6 +29954,451 @@ } } }, + "\/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": [], + "Key": [], + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "File token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, "\/users": { "get": { "summary": "List users", @@ -33923,6 +34751,30 @@ "buckets" ] }, + "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", @@ -34331,6 +35183,30 @@ "keys" ] }, + "devKeyList": { + "description": "Dev Keys List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of devKeys documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "devKeys": { + "type": "array", + "description": "List of devKeys.", + "items": { + "$ref": "#\/components\/schemas\/devKey" + }, + "x-example": "" + } + }, + "required": [ + "total", + "devKeys" + ] + }, "platformList": { "description": "Platforms List", "type": "object", @@ -36802,6 +37678,50 @@ "antivirus" ] }, + "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", @@ -38603,6 +39523,14 @@ }, "x-example": {} }, + "devKeys": { + "type": "array", + "description": "List of dev keys.", + "items": { + "$ref": "#\/components\/schemas\/devKey" + }, + "x-example": {} + }, "smtpEnabled": { "type": "boolean", "description": "Status for custom SMTP", @@ -38786,6 +39714,7 @@ "platforms", "webhooks", "keys", + "devKeys", "smtpEnabled", "smtpSenderName", "smtpSenderEmail", @@ -38976,6 +39905,65 @@ "sdks" ] }, + "devKey": { + "description": "DevKey", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Key ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Key creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Key update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Key name.", + "x-example": "Dev API Key" + }, + "expire": { + "type": "string", + "description": "Key expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "919c2d18fb5d4...a2ae413da83346ad2" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "sdks": { + "type": "array", + "description": "List of SDK user agents that used this key.", + "items": { + "type": "string" + }, + "x-example": "appwrite:flutter" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "expire", + "secret", + "accessedAt", + "sdks" + ] + }, "mockNumber": { "description": "Mock Number", "type": "object", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index df5948090b..1f33ccf24b 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -8136,7 +8136,7 @@ }, "x-appwrite": { "method": "list", - "weight": 368, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -8209,7 +8209,7 @@ }, "x-appwrite": { "method": "create", - "weight": 365, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -8440,7 +8440,7 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 370, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -8489,7 +8489,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 371, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -8539,7 +8539,7 @@ }, "x-appwrite": { "method": "get", - "weight": 366, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -8598,7 +8598,7 @@ }, "x-appwrite": { "method": "update", - "weight": 367, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -8826,7 +8826,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 369, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -8887,7 +8887,7 @@ }, "x-appwrite": { "method": "updateFunctionDeployment", - "weight": 374, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -8967,7 +8967,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 375, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -9050,7 +9050,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 372, + "weight": 377, "cookies": false, "type": "upload", "deprecated": false, @@ -9146,7 +9146,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 380, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -9231,7 +9231,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 377, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -9334,7 +9334,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 378, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -9431,7 +9431,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 373, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9493,7 +9493,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 376, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -9557,7 +9557,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 379, + "weight": 384, "cookies": false, "type": "location", "deprecated": false, @@ -9647,7 +9647,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 381, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -9718,7 +9718,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 384, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -9794,7 +9794,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 382, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -9910,7 +9910,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 383, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -9976,7 +9976,7 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 385, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10047,7 +10047,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 390, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -10106,7 +10106,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 388, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -10197,7 +10197,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 389, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -10266,7 +10266,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 391, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -10357,7 +10357,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 392, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -16691,7 +16691,7 @@ }, "x-appwrite": { "method": "list", - "weight": 397, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -16761,7 +16761,7 @@ }, "x-appwrite": { "method": "create", - "weight": 395, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -17007,7 +17007,7 @@ }, "x-appwrite": { "method": "listFrameworks", - "weight": 400, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17056,7 +17056,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 423, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -17106,7 +17106,7 @@ }, "x-appwrite": { "method": "get", - "weight": 396, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -17165,7 +17165,7 @@ }, "x-appwrite": { "method": "update", - "weight": 398, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -17407,7 +17407,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 399, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -17468,7 +17468,7 @@ }, "x-appwrite": { "method": "updateSiteDeployment", - "weight": 406, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -17548,7 +17548,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 405, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -17631,7 +17631,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 401, + "weight": 406, "cookies": false, "type": "upload", "deprecated": false, @@ -17732,7 +17732,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 409, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -17812,7 +17812,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 402, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -17915,7 +17915,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 403, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -18013,7 +18013,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 404, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -18075,7 +18075,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 407, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18139,7 +18139,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 408, + "weight": 413, "cookies": false, "type": "location", "deprecated": false, @@ -18229,7 +18229,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 410, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18300,7 +18300,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 412, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -18371,7 +18371,7 @@ }, "x-appwrite": { "method": "getLog", - "weight": 411, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -18433,7 +18433,7 @@ }, "x-appwrite": { "method": "deleteLog", - "weight": 413, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -18504,7 +18504,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 416, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -18563,7 +18563,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 414, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -18654,7 +18654,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 415, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -18723,7 +18723,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 417, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -18814,7 +18814,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 418, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -21127,6 +21127,463 @@ } } }, + "\/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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "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": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "File token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, "\/users": { "get": { "summary": "List users", @@ -24706,6 +25163,30 @@ "buckets" ] }, + "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", @@ -27273,6 +27754,50 @@ "antivirus" ] }, + "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", diff --git a/app/config/specs/swagger2-1.7.x-client.json b/app/config/specs/swagger2-1.7.x-client.json index 9e46409693..0dd88e6d4f 100644 --- a/app/config/specs/swagger2-1.7.x-client.json +++ b/app/config/specs/swagger2-1.7.x-client.json @@ -4918,7 +4918,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -4929,7 +4929,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -4991,7 +4991,7 @@ "tags": [ "functions" ], - "description": "", + "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.", "responses": { "201": { "description": "Execution", @@ -5002,7 +5002,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -5109,7 +5109,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function execution log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -5120,7 +5120,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -5761,7 +5761,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -5845,7 +5845,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -7653,6 +7653,451 @@ } ] } + }, + "\/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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": "", + "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": "", + "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": "", + "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": "", + "in": "path" + } + ] + } } }, "tags": [ @@ -7875,6 +8320,31 @@ "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", @@ -9082,6 +9552,50 @@ "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", diff --git a/app/config/specs/swagger2-1.7.x-console.json b/app/config/specs/swagger2-1.7.x-console.json index 2c1d094b63..94dad7013c 100644 --- a/app/config/specs/swagger2-1.7.x-console.json +++ b/app/config/specs/swagger2-1.7.x-console.json @@ -4555,7 +4555,7 @@ "tags": [ "console" ], - "description": "", + "description": "Check if a resource ID is available.", "responses": { "204": { "description": "No content" @@ -4563,7 +4563,7 @@ }, "x-appwrite": { "method": "getResource", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -9189,7 +9189,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the project's functions. You can use the query params to filter your results.", "responses": { "200": { "description": "Functions List", @@ -9200,7 +9200,7 @@ }, "x-appwrite": { "method": "list", - "weight": 367, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -9260,7 +9260,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", "responses": { "201": { "description": "Function", @@ -9271,7 +9271,7 @@ }, "x-appwrite": { "method": "create", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -9510,7 +9510,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all runtimes that are currently active on your instance.", "responses": { "200": { "description": "Runtimes List", @@ -9521,7 +9521,7 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 369, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -9560,7 +9560,7 @@ "tags": [ "functions" ], - "description": "", + "description": "List allowed function specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -9571,7 +9571,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 370, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -9611,7 +9611,7 @@ "tags": [ "functions" ], - "description": "", + "description": "List available function templates. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", "responses": { "200": { "description": "Function Templates List", @@ -9622,7 +9622,7 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 393, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -9706,7 +9706,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function template using ID. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", "responses": { "200": { "description": "Template Function", @@ -9717,7 +9717,7 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -9765,7 +9765,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for all functions in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageFunctions", @@ -9776,7 +9776,7 @@ }, "x-appwrite": { "method": "listUsage", - "weight": 386, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -9836,7 +9836,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function by its unique ID.", "responses": { "200": { "description": "Function", @@ -9847,7 +9847,7 @@ }, "x-appwrite": { "method": "get", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -9894,7 +9894,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update function by its unique ID.", "responses": { "200": { "description": "Function", @@ -9905,7 +9905,7 @@ }, "x-appwrite": { "method": "update", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -10141,7 +10141,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a function by its unique ID.", "responses": { "204": { "description": "No content" @@ -10149,7 +10149,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 368, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -10198,7 +10198,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", "responses": { "200": { "description": "Function", @@ -10209,7 +10209,7 @@ }, "x-appwrite": { "method": "updateFunctionDeployment", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -10276,7 +10276,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the function's code deployments. You can use the query params to filter your results.", "responses": { "200": { "description": "Deployments List", @@ -10287,7 +10287,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -10355,7 +10355,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", "responses": { "202": { "description": "Deployment", @@ -10366,7 +10366,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 371, + "weight": 372, "cookies": false, "type": "upload", "deprecated": false, @@ -10446,7 +10446,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "202": { "description": "Deployment", @@ -10457,7 +10457,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 379, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -10530,7 +10530,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", "responses": { "202": { "description": "Deployment", @@ -10541,7 +10541,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -10635,7 +10635,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", "responses": { "202": { "description": "Deployment", @@ -10646,7 +10646,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -10732,7 +10732,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function deployment by its unique ID.", "responses": { "200": { "description": "Deployment", @@ -10743,7 +10743,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -10796,7 +10796,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a code deployment by its unique ID.", "responses": { "204": { "description": "No content" @@ -10804,7 +10804,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -10861,7 +10861,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", "responses": { "200": { "description": "File", @@ -10872,7 +10872,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 378, + "weight": 379, "cookies": false, "type": "location", "deprecated": false, @@ -10946,7 +10946,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Deployment", @@ -10957,7 +10957,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -11014,7 +11014,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -11025,7 +11025,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -11087,7 +11087,7 @@ "tags": [ "functions" ], - "description": "", + "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.", "responses": { "201": { "description": "Execution", @@ -11098,7 +11098,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -11205,7 +11205,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function execution log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -11216,7 +11216,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -11272,7 +11272,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a function execution by its unique ID.", "responses": { "204": { "description": "No content" @@ -11280,7 +11280,7 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -11337,7 +11337,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageFunction", @@ -11348,7 +11348,7 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11416,7 +11416,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all variables of a specific function.", "responses": { "200": { "description": "Variables List", @@ -11427,7 +11427,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11474,7 +11474,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", "responses": { "201": { "description": "Variable", @@ -11485,7 +11485,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -11565,7 +11565,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -11576,7 +11576,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -11631,7 +11631,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -11642,7 +11642,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11725,7 +11725,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a variable by its unique ID.", "responses": { "204": { "description": "No content" @@ -11733,7 +11733,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -13718,7 +13718,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -13792,7 +13792,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -13949,7 +13949,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -14103,7 +14103,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14297,7 +14297,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -14490,7 +14490,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -14607,7 +14607,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14722,7 +14722,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14776,7 +14776,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14837,7 +14837,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -14910,7 +14910,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14983,7 +14983,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -15057,7 +15057,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -15171,7 +15171,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -15283,7 +15283,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15373,7 +15373,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -15461,7 +15461,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 318, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -15587,7 +15587,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15711,7 +15711,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -15813,7 +15813,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -15913,7 +15913,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 319, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -16027,7 +16027,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -16139,7 +16139,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 320, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -16297,7 +16297,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -16452,7 +16452,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -16554,7 +16554,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16654,7 +16654,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -16756,7 +16756,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16856,7 +16856,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -16958,7 +16958,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -17058,7 +17058,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -17160,7 +17160,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -17260,7 +17260,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -17314,7 +17314,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17375,7 +17375,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -17448,7 +17448,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17521,7 +17521,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -17593,7 +17593,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -17682,7 +17682,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -17741,7 +17741,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17819,7 +17819,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -17880,7 +17880,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -17953,7 +17953,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -18033,7 +18033,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -18122,7 +18122,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -18184,7 +18184,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18256,7 +18256,7 @@ }, "x-appwrite": { "method": "list", - "weight": 310, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -18421,7 +18421,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 312, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -18484,6 +18484,89 @@ ] } }, + "\/migrations\/csv": { + "post": { + "summary": "Import documents from a CSV", + "operationId": "migrationsCreateCsvMigration", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "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.", + "responses": { + "202": { + "description": "Migration", + "schema": { + "$ref": "#\/definitions\/migration" + } + } + }, + "x-appwrite": { + "method": "createCsvMigration", + "weight": 310, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-csv-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-csv.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "bucketId": { + "type": "string", + "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).", + "default": null, + "x-example": "" + }, + "fileId": { + "type": "string", + "description": "File ID.", + "default": null, + "x-example": "" + }, + "resourceId": { + "type": "string", + "description": "Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.", + "default": null, + "x-example": "[ID1:ID2]" + } + }, + "required": [ + "bucketId", + "fileId", + "resourceId" + ] + } + } + ] + } + }, "\/migrations\/firebase": { "post": { "summary": "Migrate Firebase data", @@ -18587,7 +18670,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 313, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -18777,7 +18860,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 315, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -19009,7 +19092,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 314, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -19121,7 +19204,7 @@ }, "x-appwrite": { "method": "get", - "weight": 311, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -19178,7 +19261,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 316, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -19230,7 +19313,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 317, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -24582,7 +24665,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Create a new proxy rule for serving Appwrite's API on custom domain.", "responses": { "201": { "description": "Rule", @@ -24593,7 +24676,7 @@ }, "x-appwrite": { "method": "createAPIRule", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -24651,7 +24734,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Create a new proxy rule for executing Appwrite Function on custom domain.", "responses": { "201": { "description": "Rule", @@ -24662,7 +24745,7 @@ }, "x-appwrite": { "method": "createFunctionRule", - "weight": 426, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -24733,7 +24816,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Create a new proxy rule for to redirect from custom domain to another domain.", "responses": { "201": { "description": "Rule", @@ -24744,7 +24827,7 @@ }, "x-appwrite": { "method": "createRedirectRule", - "weight": 427, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -24829,7 +24912,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Create a new proxy rule for serving Appwrite Site on custom domain.", "responses": { "201": { "description": "Rule", @@ -24840,7 +24923,7 @@ }, "x-appwrite": { "method": "createSiteRule", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -25081,7 +25164,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all the project's sites. You can use the query params to filter your results.", "responses": { "200": { "description": "Sites List", @@ -25092,7 +25175,7 @@ }, "x-appwrite": { "method": "list", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -25152,7 +25235,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site.", "responses": { "201": { "description": "Site", @@ -25163,7 +25246,7 @@ }, "x-appwrite": { "method": "create", - "weight": 394, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -25244,7 +25327,7 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "default": 15, + "default": 30, "x-example": 1 }, "installCommand": { @@ -25417,7 +25500,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all frameworks that are currently available on the server instance.", "responses": { "200": { "description": "Frameworks List", @@ -25428,7 +25511,7 @@ }, "x-appwrite": { "method": "listFrameworks", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -25467,7 +25550,7 @@ "tags": [ "sites" ], - "description": "", + "description": "List allowed site specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -25478,7 +25561,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -25518,7 +25601,7 @@ "tags": [ "sites" ], - "description": "", + "description": "List available site templates. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", "responses": { "200": { "description": "Site Templates List", @@ -25529,7 +25612,7 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -25613,7 +25696,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site template using ID. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", "responses": { "200": { "description": "Template Site", @@ -25624,7 +25707,7 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -25672,7 +25755,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get usage metrics and statistics for all sites in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageSites", @@ -25683,7 +25766,7 @@ }, "x-appwrite": { "method": "listUsage", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -25743,7 +25826,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site by its unique ID.", "responses": { "200": { "description": "Site", @@ -25754,7 +25837,7 @@ }, "x-appwrite": { "method": "get", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -25801,7 +25884,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update site by its unique ID.", "responses": { "200": { "description": "Site", @@ -25812,7 +25895,7 @@ }, "x-appwrite": { "method": "update", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -25895,7 +25978,7 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "default": 15, + "default": 30, "x-example": 1 }, "installCommand": { @@ -26062,7 +26145,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site by its unique ID.", "responses": { "204": { "description": "No content" @@ -26070,7 +26153,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -26119,7 +26202,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", "responses": { "200": { "description": "Site", @@ -26130,7 +26213,7 @@ }, "x-appwrite": { "method": "updateSiteDeployment", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -26197,7 +26280,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all the site's code deployments. You can use the query params to filter your results.", "responses": { "200": { "description": "Deployments List", @@ -26208,7 +26291,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -26276,7 +26359,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", "responses": { "202": { "description": "Deployment", @@ -26287,7 +26370,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 400, + "weight": 401, "cookies": false, "type": "upload", "deprecated": false, @@ -26375,7 +26458,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "202": { "description": "Deployment", @@ -26386,7 +26469,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 408, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -26442,7 +26525,7 @@ }, "\/sites\/{siteId}\/deployments\/template": { "post": { - "summary": "Create deployment", + "summary": "Create template deployment", "operationId": "sitesCreateTemplateDeployment", "consumes": [ "application\/json" @@ -26453,7 +26536,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", "responses": { "202": { "description": "Deployment", @@ -26464,7 +26547,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 401, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -26558,7 +26641,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", "responses": { "202": { "description": "Deployment", @@ -26569,7 +26652,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -26656,7 +26739,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site deployment by its unique ID.", "responses": { "200": { "description": "Deployment", @@ -26667,7 +26750,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -26720,7 +26803,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site deployment by its unique ID.", "responses": { "204": { "description": "No content" @@ -26728,7 +26811,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26785,7 +26868,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", "responses": { "200": { "description": "File", @@ -26796,7 +26879,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 407, + "weight": 408, "cookies": false, "type": "location", "deprecated": false, @@ -26870,7 +26953,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Cancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Deployment", @@ -26881,7 +26964,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -26938,7 +27021,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all site logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -26949,7 +27032,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -27010,7 +27093,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site request log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -27021,7 +27104,7 @@ }, "x-appwrite": { "method": "getLog", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -27076,7 +27159,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site log by its unique ID.", "responses": { "204": { "description": "No content" @@ -27084,7 +27167,7 @@ }, "x-appwrite": { "method": "deleteLog", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -27141,7 +27224,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get usage metrics and statistics for a for a specific site. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageSite", @@ -27152,7 +27235,7 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -27220,7 +27303,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all variables of a specific site.", "responses": { "200": { "description": "Variables List", @@ -27231,7 +27314,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 415, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -27278,7 +27361,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", "responses": { "201": { "description": "Variable", @@ -27289,7 +27372,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -27369,7 +27452,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -27380,7 +27463,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -27435,7 +27518,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -27446,7 +27529,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -27529,7 +27612,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a variable by its unique ID.", "responses": { "204": { "description": "No content" @@ -27537,7 +27620,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -30019,6 +30102,451 @@ ] } }, + "\/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": [], + "Key": [], + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "File token ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, "\/users": { "get": { "summary": "List users", @@ -34386,6 +34914,31 @@ "buckets" ] }, + "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", @@ -37302,6 +37855,50 @@ "antivirus" ] }, + "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", @@ -40527,6 +41124,18 @@ }, "x-example": [] }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, "builds": { "type": "array", "description": "Aggregated number of functions build per period.", @@ -40589,6 +41198,24 @@ "$ref": "#\/definitions\/metric" }, "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] } }, "required": [ @@ -40606,13 +41233,17 @@ "functions", "deployments", "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", "builds", "buildsStorage", "buildsTime", "buildsMbSeconds", "executions", "executionsTime", - "executionsMbSeconds" + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" ] }, "usageFunction": { @@ -40642,6 +41273,18 @@ "x-example": 0, "format": "int32" }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, "buildsStorageTotal": { "type": "integer", "description": "total aggregated sum of function builds storage.", @@ -40654,6 +41297,12 @@ "x-example": 0, "format": "int32" }, + "buildsTimeAverage": { + "type": "integer", + "description": "Average builds compute time.", + "x-example": 0, + "format": "int32" + }, "buildsMbSecondsTotal": { "type": "integer", "description": "Total aggregated sum of function builds mbSeconds.", @@ -40758,6 +41407,286 @@ "$ref": "#\/definitions\/metric" }, "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsSuccessTotal", + "buildsFailedTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsTimeAverage", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" + ] + }, + "usageSites": { + "description": "UsageSites", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of functions deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of functions deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of functions build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of functions build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of functions execution.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of functions deployment per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of functions deployment storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "builds": { + "type": "array", + "description": "Aggregated number of functions build per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of functions build storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of functions build compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of functions build mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of functions execution per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of functions execution compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of functions mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "sitesTotal": { + "type": "integer", + "description": "Total aggregated number of sites.", + "x-example": 0, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "Aggregated number of sites per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "requestsTotal": { + "type": "integer", + "description": "Total aggregated number of requests.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "inboundTotal": { + "type": "integer", + "description": "Total aggregated inbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "inbound": { + "type": "array", + "description": "Aggregated number of inbound bandwidth per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "outboundTotal": { + "type": "integer", + "description": "Total aggregated outbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "outbound": { + "type": "array", + "description": "Aggregated number of outbound bandwidth per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] } }, "required": [ @@ -40773,146 +41702,25 @@ "executionsMbSecondsTotal", "deployments", "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", "builds", "buildsStorage", "buildsTime", "buildsMbSeconds", "executions", "executionsTime", - "executionsMbSeconds" - ] - }, - "usageSites": { - "description": "UsageSites", - "type": "object", - "properties": { - "range": { - "type": "string", - "description": "Time range of the usage stats.", - "x-example": "30d" - }, - "sitesTotal": { - "type": "integer", - "description": "Total aggregated number of sites.", - "x-example": 0, - "format": "int32" - }, - "deploymentsTotal": { - "type": "integer", - "description": "Total aggregated number of sites deployments.", - "x-example": 0, - "format": "int32" - }, - "deploymentsStorageTotal": { - "type": "integer", - "description": "Total aggregated sum of sites deployment storage.", - "x-example": 0, - "format": "int32" - }, - "buildsTotal": { - "type": "integer", - "description": "Total aggregated number of sites build.", - "x-example": 0, - "format": "int32" - }, - "buildsStorageTotal": { - "type": "integer", - "description": "total aggregated sum of sites build storage.", - "x-example": 0, - "format": "int32" - }, - "buildsTimeTotal": { - "type": "integer", - "description": "Total aggregated sum of sites build compute time.", - "x-example": 0, - "format": "int32" - }, - "buildsMbSecondsTotal": { - "type": "integer", - "description": "Total aggregated sum of sites build mbSeconds.", - "x-example": 0, - "format": "int32" - }, - "sites": { - "type": "array", - "description": "Aggregated number of sites per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": 0 - }, - "deployments": { - "type": "array", - "description": "Aggregated number of sites deployment per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "deploymentsStorage": { - "type": "array", - "description": "Aggregated number of sites deployment storage per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "builds": { - "type": "array", - "description": "Aggregated number of sites build per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsStorage": { - "type": "array", - "description": "Aggregated sum of sites build storage per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsTime": { - "type": "array", - "description": "Aggregated sum of sites build compute time per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsMbSeconds": { - "type": "array", - "description": "Aggregated sum of sites build mbSeconds per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - } - }, - "required": [ - "range", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed", "sitesTotal", - "deploymentsTotal", - "deploymentsStorageTotal", - "buildsTotal", - "buildsStorageTotal", - "buildsTimeTotal", - "buildsMbSecondsTotal", "sites", - "deployments", - "deploymentsStorage", - "builds", - "buildsStorage", - "buildsTime", - "buildsMbSeconds" + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound" ] }, "usageSite": { @@ -40926,43 +41734,79 @@ }, "deploymentsTotal": { "type": "integer", - "description": "Total aggregated number of site deployments.", + "description": "Total aggregated number of function deployments.", "x-example": 0, "format": "int32" }, "deploymentsStorageTotal": { "type": "integer", - "description": "Total aggregated sum of site deployments storage.", + "description": "Total aggregated sum of function deployments storage.", "x-example": 0, "format": "int32" }, "buildsTotal": { "type": "integer", - "description": "Total aggregated number of site builds.", + "description": "Total aggregated number of function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", "x-example": 0, "format": "int32" }, "buildsStorageTotal": { "type": "integer", - "description": "total aggregated sum of site builds storage.", + "description": "total aggregated sum of function builds storage.", "x-example": 0, "format": "int32" }, "buildsTimeTotal": { "type": "integer", - "description": "Total aggregated sum of site builds compute time.", + "description": "Total aggregated sum of function builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeAverage": { + "type": "integer", + "description": "Average builds compute time.", "x-example": 0, "format": "int32" }, "buildsMbSecondsTotal": { "type": "integer", - "description": "Total aggregated sum of site builds mbSeconds.", + "description": "Total aggregated sum of function builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions mbSeconds.", "x-example": 0, "format": "int32" }, "deployments": { "type": "array", - "description": "Aggregated number of site deployments per period.", + "description": "Aggregated number of function deployments per period.", "items": { "type": "object", "$ref": "#\/definitions\/metric" @@ -40971,7 +41815,7 @@ }, "deploymentsStorage": { "type": "array", - "description": "Aggregated number of site deployments storage per period.", + "description": "Aggregated number of function deployments storage per period.", "items": { "type": "object", "$ref": "#\/definitions\/metric" @@ -40980,7 +41824,7 @@ }, "builds": { "type": "array", - "description": "Aggregated number of site builds per period.", + "description": "Aggregated number of function builds per period.", "items": { "type": "object", "$ref": "#\/definitions\/metric" @@ -40989,7 +41833,7 @@ }, "buildsStorage": { "type": "array", - "description": "Aggregated sum of site builds storage per period.", + "description": "Aggregated sum of function builds storage per period.", "items": { "type": "object", "$ref": "#\/definitions\/metric" @@ -40998,7 +41842,7 @@ }, "buildsTime": { "type": "array", - "description": "Aggregated sum of site builds compute time per period.", + "description": "Aggregated sum of function builds compute time per period.", "items": { "type": "object", "$ref": "#\/definitions\/metric" @@ -41007,7 +41851,97 @@ }, "buildsMbSeconds": { "type": "array", - "description": "Aggregated number of site builds mbSeconds per period.", + "description": "Aggregated number of function builds mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of function executions per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of function executions compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of function mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "requestsTotal": { + "type": "integer", + "description": "Total aggregated number of requests.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "inboundTotal": { + "type": "integer", + "description": "Total aggregated inbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "inbound": { + "type": "array", + "description": "Aggregated number of inbound bandwidth per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "outboundTotal": { + "type": "integer", + "description": "Total aggregated outbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "outbound": { + "type": "array", + "description": "Aggregated number of outbound bandwidth per period.", "items": { "type": "object", "$ref": "#\/definitions\/metric" @@ -41020,15 +41954,32 @@ "deploymentsTotal", "deploymentsStorageTotal", "buildsTotal", + "buildsSuccessTotal", + "buildsFailedTotal", "buildsStorageTotal", "buildsTimeTotal", + "buildsTimeAverage", "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", "deployments", "deploymentsStorage", "builds", "buildsStorage", "buildsTime", - "buildsMbSeconds" + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed", + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound" ] }, "usageProject": { @@ -41531,11 +42482,21 @@ "description": "Console Variables", "type": "object", "properties": { - "_APP_DOMAIN_TARGET": { + "_APP_DOMAIN_TARGET_CNAME": { "type": "string", "description": "CNAME target for your Appwrite custom domains.", "x-example": "appwrite.io" }, + "_APP_DOMAIN_TARGET_A": { + "type": "string", + "description": "A target for your Appwrite custom domains.", + "x-example": "127.0.0.1" + }, + "_APP_DOMAIN_TARGET_AAAA": { + "type": "string", + "description": "AAAA target for your Appwrite custom domains.", + "x-example": "::1" + }, "_APP_STORAGE_LIMIT": { "type": "integer", "description": "Maximum file size allowed for file upload in bytes.", @@ -41590,7 +42551,9 @@ } }, "required": [ - "_APP_DOMAIN_TARGET", + "_APP_DOMAIN_TARGET_CNAME", + "_APP_DOMAIN_TARGET_A", + "_APP_DOMAIN_TARGET_AAAA", "_APP_STORAGE_LIMIT", "_APP_COMPUTE_SIZE_LIMIT", "_APP_USAGE_STATS", @@ -42133,6 +43096,11 @@ "user" ] }, + "resourceId": { + "type": "string", + "description": "Id of the resource to migrate.", + "x-example": "databaseId:collectionId" + }, "statusCounters": { "type": "object", "additionalProperties": true, @@ -42163,6 +43131,7 @@ "source", "destination", "resources", + "resourceId", "statusCounters", "resourceData", "errors" diff --git a/app/config/specs/swagger2-1.7.x-server.json b/app/config/specs/swagger2-1.7.x-server.json index c89973e2a3..28c56410fb 100644 --- a/app/config/specs/swagger2-1.7.x-server.json +++ b/app/config/specs/swagger2-1.7.x-server.json @@ -8271,7 +8271,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the project's functions. You can use the query params to filter your results.", "responses": { "200": { "description": "Functions List", @@ -8282,7 +8282,7 @@ }, "x-appwrite": { "method": "list", - "weight": 367, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -8343,7 +8343,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", "responses": { "201": { "description": "Function", @@ -8354,7 +8354,7 @@ }, "x-appwrite": { "method": "create", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -8594,7 +8594,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all runtimes that are currently active on your instance.", "responses": { "200": { "description": "Runtimes List", @@ -8605,7 +8605,7 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 369, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -8645,7 +8645,7 @@ "tags": [ "functions" ], - "description": "", + "description": "List allowed function specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -8656,7 +8656,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 370, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -8697,7 +8697,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function by its unique ID.", "responses": { "200": { "description": "Function", @@ -8708,7 +8708,7 @@ }, "x-appwrite": { "method": "get", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -8756,7 +8756,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update function by its unique ID.", "responses": { "200": { "description": "Function", @@ -8767,7 +8767,7 @@ }, "x-appwrite": { "method": "update", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -9004,7 +9004,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a function by its unique ID.", "responses": { "204": { "description": "No content" @@ -9012,7 +9012,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 368, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -9062,7 +9062,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", "responses": { "200": { "description": "Function", @@ -9073,7 +9073,7 @@ }, "x-appwrite": { "method": "updateFunctionDeployment", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -9141,7 +9141,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the function's code deployments. You can use the query params to filter your results.", "responses": { "200": { "description": "Deployments List", @@ -9152,7 +9152,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9221,7 +9221,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", "responses": { "202": { "description": "Deployment", @@ -9232,7 +9232,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 371, + "weight": 372, "cookies": false, "type": "upload", "deprecated": false, @@ -9313,7 +9313,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "202": { "description": "Deployment", @@ -9324,7 +9324,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 379, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -9398,7 +9398,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", "responses": { "202": { "description": "Deployment", @@ -9409,7 +9409,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -9504,7 +9504,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", "responses": { "202": { "description": "Deployment", @@ -9515,7 +9515,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9602,7 +9602,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function deployment by its unique ID.", "responses": { "200": { "description": "Deployment", @@ -9613,7 +9613,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -9667,7 +9667,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a code deployment by its unique ID.", "responses": { "204": { "description": "No content" @@ -9675,7 +9675,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9733,7 +9733,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", "responses": { "200": { "description": "File", @@ -9744,7 +9744,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 378, + "weight": 379, "cookies": false, "type": "location", "deprecated": false, @@ -9819,7 +9819,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Deployment", @@ -9830,7 +9830,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -9888,7 +9888,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -9899,7 +9899,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -9963,7 +9963,7 @@ "tags": [ "functions" ], - "description": "", + "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.", "responses": { "201": { "description": "Execution", @@ -9974,7 +9974,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -10083,7 +10083,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a function execution log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -10094,7 +10094,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10152,7 +10152,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a function execution by its unique ID.", "responses": { "204": { "description": "No content" @@ -10160,7 +10160,7 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -10218,7 +10218,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a list of all variables of a specific function.", "responses": { "200": { "description": "Variables List", @@ -10229,7 +10229,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10277,7 +10277,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", "responses": { "201": { "description": "Variable", @@ -10288,7 +10288,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -10369,7 +10369,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get a variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -10380,7 +10380,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -10436,7 +10436,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Update variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -10447,7 +10447,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -10531,7 +10531,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Delete a variable by its unique ID.", "responses": { "204": { "description": "No content" @@ -10539,7 +10539,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -12568,7 +12568,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -12643,7 +12643,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -12801,7 +12801,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -12956,7 +12956,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -13151,7 +13151,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -13345,7 +13345,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -13463,7 +13463,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -13579,7 +13579,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -13634,7 +13634,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -13696,7 +13696,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -13770,7 +13770,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13844,7 +13844,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -13919,7 +13919,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -14034,7 +14034,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -14147,7 +14147,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -14238,7 +14238,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -14327,7 +14327,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 318, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -14454,7 +14454,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14579,7 +14579,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -14682,7 +14682,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -14783,7 +14783,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 319, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -14898,7 +14898,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -15011,7 +15011,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 320, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -15170,7 +15170,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -15326,7 +15326,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -15429,7 +15429,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -15530,7 +15530,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15633,7 +15633,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15734,7 +15734,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -15837,7 +15837,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -15938,7 +15938,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16041,7 +16041,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16142,7 +16142,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -16197,7 +16197,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16259,7 +16259,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -16333,7 +16333,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16407,7 +16407,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -16480,7 +16480,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -16570,7 +16570,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -16630,7 +16630,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16709,7 +16709,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16771,7 +16771,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -16845,7 +16845,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16926,7 +16926,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -17017,7 +17017,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17080,7 +17080,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17143,7 +17143,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all the project's sites. You can use the query params to filter your results.", "responses": { "200": { "description": "Sites List", @@ -17154,7 +17154,7 @@ }, "x-appwrite": { "method": "list", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -17215,7 +17215,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site.", "responses": { "201": { "description": "Site", @@ -17226,7 +17226,7 @@ }, "x-appwrite": { "method": "create", - "weight": 394, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -17308,7 +17308,7 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "default": 15, + "default": 30, "x-example": 1 }, "installCommand": { @@ -17481,7 +17481,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all frameworks that are currently available on the server instance.", "responses": { "200": { "description": "Frameworks List", @@ -17492,7 +17492,7 @@ }, "x-appwrite": { "method": "listFrameworks", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -17532,7 +17532,7 @@ "tags": [ "sites" ], - "description": "", + "description": "List allowed site specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -17543,7 +17543,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -17584,7 +17584,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site by its unique ID.", "responses": { "200": { "description": "Site", @@ -17595,7 +17595,7 @@ }, "x-appwrite": { "method": "get", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -17643,7 +17643,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update site by its unique ID.", "responses": { "200": { "description": "Site", @@ -17654,7 +17654,7 @@ }, "x-appwrite": { "method": "update", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -17738,7 +17738,7 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "default": 15, + "default": 30, "x-example": 1 }, "installCommand": { @@ -17905,7 +17905,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site by its unique ID.", "responses": { "204": { "description": "No content" @@ -17913,7 +17913,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -17963,7 +17963,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", "responses": { "200": { "description": "Site", @@ -17974,7 +17974,7 @@ }, "x-appwrite": { "method": "updateSiteDeployment", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -18042,7 +18042,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all the site's code deployments. You can use the query params to filter your results.", "responses": { "200": { "description": "Deployments List", @@ -18053,7 +18053,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -18122,7 +18122,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", "responses": { "202": { "description": "Deployment", @@ -18133,7 +18133,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 400, + "weight": 401, "cookies": false, "type": "upload", "deprecated": false, @@ -18222,7 +18222,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "202": { "description": "Deployment", @@ -18233,7 +18233,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 408, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -18290,7 +18290,7 @@ }, "\/sites\/{siteId}\/deployments\/template": { "post": { - "summary": "Create deployment", + "summary": "Create template deployment", "operationId": "sitesCreateTemplateDeployment", "consumes": [ "application\/json" @@ -18301,7 +18301,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", "responses": { "202": { "description": "Deployment", @@ -18312,7 +18312,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 401, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -18407,7 +18407,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", "responses": { "202": { "description": "Deployment", @@ -18418,7 +18418,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -18506,7 +18506,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site deployment by its unique ID.", "responses": { "200": { "description": "Deployment", @@ -18517,7 +18517,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -18571,7 +18571,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site deployment by its unique ID.", "responses": { "204": { "description": "No content" @@ -18579,7 +18579,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -18637,7 +18637,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", "responses": { "200": { "description": "File", @@ -18648,7 +18648,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 407, + "weight": 408, "cookies": false, "type": "location", "deprecated": false, @@ -18723,7 +18723,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Cancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Deployment", @@ -18734,7 +18734,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -18792,7 +18792,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all site logs. You can use the query params to filter your results.", "responses": { "200": { "description": "Executions List", @@ -18803,7 +18803,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18865,7 +18865,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a site request log by its unique ID.", "responses": { "200": { "description": "Execution", @@ -18876,7 +18876,7 @@ }, "x-appwrite": { "method": "getLog", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -18932,7 +18932,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a site log by its unique ID.", "responses": { "204": { "description": "No content" @@ -18940,7 +18940,7 @@ }, "x-appwrite": { "method": "deleteLog", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -18998,7 +18998,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a list of all variables of a specific site.", "responses": { "200": { "description": "Variables List", @@ -19009,7 +19009,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 415, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -19057,7 +19057,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", "responses": { "201": { "description": "Variable", @@ -19068,7 +19068,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -19149,7 +19149,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Get a variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -19160,7 +19160,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -19216,7 +19216,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Update variable by its unique ID.", "responses": { "200": { "description": "Variable", @@ -19227,7 +19227,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -19311,7 +19311,7 @@ "tags": [ "sites" ], - "description": "", + "description": "Delete a variable by its unique ID.", "responses": { "204": { "description": "No content" @@ -19319,7 +19319,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -21628,6 +21628,463 @@ ] } }, + "\/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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "File token ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, "\/users": { "get": { "summary": "List users", @@ -25231,6 +25688,31 @@ "buckets" ] }, + "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", @@ -27822,6 +28304,50 @@ "antivirus" ] }, + "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", diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index dc5600aa86..4359443278 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -4929,7 +4929,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 384, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -5002,7 +5002,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 382, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -5120,7 +5120,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 383, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -7653,6 +7653,451 @@ } ] } + }, + "\/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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": "", + "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": "", + "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": "", + "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": "", + "in": "path" + } + ] + } } }, "tags": [ @@ -7875,6 +8320,31 @@ "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", @@ -9082,6 +9552,50 @@ "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", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 76f1152287..fa788f8268 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -4563,7 +4563,7 @@ }, "x-appwrite": { "method": "getResource", - "weight": 424, + "weight": 429, "cookies": false, "type": "", "deprecated": false, @@ -9200,7 +9200,7 @@ }, "x-appwrite": { "method": "list", - "weight": 368, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -9271,7 +9271,7 @@ }, "x-appwrite": { "method": "create", - "weight": 365, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -9521,7 +9521,7 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 370, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9571,7 +9571,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 371, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9622,7 +9622,7 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 394, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -9717,7 +9717,7 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 393, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -9776,7 +9776,7 @@ }, "x-appwrite": { "method": "listUsage", - "weight": 387, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -9847,7 +9847,7 @@ }, "x-appwrite": { "method": "get", - "weight": 366, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -9905,7 +9905,7 @@ }, "x-appwrite": { "method": "update", - "weight": 367, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -10149,7 +10149,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 369, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -10209,7 +10209,7 @@ }, "x-appwrite": { "method": "updateFunctionDeployment", - "weight": 374, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -10287,7 +10287,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 375, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -10366,7 +10366,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 372, + "weight": 377, "cookies": false, "type": "upload", "deprecated": false, @@ -10457,7 +10457,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 380, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -10541,7 +10541,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 377, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -10646,7 +10646,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 378, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10743,7 +10743,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 373, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -10804,7 +10804,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 376, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -10872,7 +10872,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 379, + "weight": 384, "cookies": false, "type": "location", "deprecated": false, @@ -10957,7 +10957,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 381, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11025,7 +11025,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 384, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -11098,7 +11098,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 382, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -11216,7 +11216,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 383, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -11280,7 +11280,7 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 385, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11348,7 +11348,7 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 386, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11427,7 +11427,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 390, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -11485,7 +11485,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 388, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -11576,7 +11576,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 389, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -11642,7 +11642,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 391, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -11733,7 +11733,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 392, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -21190,6 +21190,385 @@ ] } }, + "\/projects\/{projectId}\/dev-keys": { + "get": { + "summary": "List dev keys", + "operationId": "projectsListDevKeys", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "List all the project\\'s dev keys. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.'", + "responses": { + "200": { + "description": "Dev Keys List", + "schema": { + "$ref": "#\/definitions\/devKeyList" + } + } + }, + "x-appwrite": { + "method": "listDevKeys", + "weight": 368, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-dev-keys.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the project\\'s dev keys. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.'", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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: accessedAt, expire", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create dev key", + "operationId": "projectsCreateDevKey", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Create a new project dev key. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development. Strictly meant for development purposes only.", + "responses": { + "201": { + "description": "DevKey", + "schema": { + "$ref": "#\/definitions\/devKey" + } + } + }, + "x-appwrite": { + "method": "createDevKey", + "weight": 365, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new project dev key. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development. Strictly meant for development purposes only.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "default": null, + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format.", + "default": null, + "x-example": null + } + }, + "required": [ + "name", + "expire" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/dev-keys\/{keyId}": { + "get": { + "summary": "Get dev key", + "operationId": "projectsGetDevKey", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a project\\'s dev key by its unique ID. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.", + "responses": { + "200": { + "description": "DevKey", + "schema": { + "$ref": "#\/definitions\/devKey" + } + } + }, + "x-appwrite": { + "method": "getDevKey", + "weight": 367, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a project\\'s dev key by its unique ID. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "put": { + "summary": "Update dev key", + "operationId": "projectsUpdateDevKey", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update a project\\'s dev key by its unique ID. Use this endpoint to update a project\\'s dev key name or expiration time.'", + "responses": { + "200": { + "description": "DevKey", + "schema": { + "$ref": "#\/definitions\/devKey" + } + } + }, + "x-appwrite": { + "method": "updateDevKey", + "weight": 366, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a project\\'s dev key by its unique ID. Use this endpoint to update a project\\'s dev key name or expiration time.'", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "default": null, + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format.", + "default": null, + "x-example": null + } + }, + "required": [ + "name", + "expire" + ] + } + } + ] + }, + "delete": { + "summary": "Delete dev key", + "operationId": "projectsDeleteDevKey", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "projects" + ], + "description": "Delete a project\\'s dev key by its unique ID. Once deleted, the key will no longer allow bypassing of rate limits and better logging of errors.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDevKey", + "weight": 369, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a project\\'s dev key by its unique ID. Once deleted, the key will no longer allow bypassing of rate limits and better logging of errors.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, "\/projects\/{projectId}\/jwts": { "post": { "summary": "Create JWT", @@ -24676,7 +25055,7 @@ }, "x-appwrite": { "method": "createAPIRule", - "weight": 425, + "weight": 430, "cookies": false, "type": "", "deprecated": false, @@ -24745,7 +25124,7 @@ }, "x-appwrite": { "method": "createFunctionRule", - "weight": 427, + "weight": 432, "cookies": false, "type": "", "deprecated": false, @@ -24827,7 +25206,7 @@ }, "x-appwrite": { "method": "createRedirectRule", - "weight": 428, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -24923,7 +25302,7 @@ }, "x-appwrite": { "method": "createSiteRule", - "weight": 426, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -25175,7 +25554,7 @@ }, "x-appwrite": { "method": "list", - "weight": 397, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -25246,7 +25625,7 @@ }, "x-appwrite": { "method": "create", - "weight": 395, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -25511,7 +25890,7 @@ }, "x-appwrite": { "method": "listFrameworks", - "weight": 400, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -25561,7 +25940,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 423, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -25612,7 +25991,7 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 419, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -25707,7 +26086,7 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 420, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -25766,7 +26145,7 @@ }, "x-appwrite": { "method": "listUsage", - "weight": 421, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -25837,7 +26216,7 @@ }, "x-appwrite": { "method": "get", - "weight": 396, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -25895,7 +26274,7 @@ }, "x-appwrite": { "method": "update", - "weight": 398, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -26153,7 +26532,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 399, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -26213,7 +26592,7 @@ }, "x-appwrite": { "method": "updateSiteDeployment", - "weight": 406, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -26291,7 +26670,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 405, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -26370,7 +26749,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 401, + "weight": 406, "cookies": false, "type": "upload", "deprecated": false, @@ -26469,7 +26848,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 409, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -26547,7 +26926,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 402, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26652,7 +27031,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 403, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -26750,7 +27129,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 404, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -26811,7 +27190,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 407, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -26879,7 +27258,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 408, + "weight": 413, "cookies": false, "type": "location", "deprecated": false, @@ -26964,7 +27343,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 410, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -27032,7 +27411,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 412, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -27104,7 +27483,7 @@ }, "x-appwrite": { "method": "getLog", - "weight": 411, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -27167,7 +27546,7 @@ }, "x-appwrite": { "method": "deleteLog", - "weight": 413, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -27235,7 +27614,7 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 422, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -27314,7 +27693,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 416, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -27372,7 +27751,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 414, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -27463,7 +27842,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 415, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -27529,7 +27908,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 417, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -27620,7 +27999,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 418, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -30102,6 +30481,451 @@ ] } }, + "\/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": [], + "Key": [], + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "File token ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, "\/users": { "get": { "summary": "List users", @@ -34469,6 +35293,31 @@ "buckets" ] }, + "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", @@ -34894,6 +35743,31 @@ "keys" ] }, + "devKeyList": { + "description": "Dev Keys List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of devKeys documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "devKeys": { + "type": "array", + "description": "List of devKeys.", + "items": { + "type": "object", + "$ref": "#\/definitions\/devKey" + }, + "x-example": "" + } + }, + "required": [ + "total", + "devKeys" + ] + }, "platformList": { "description": "Platforms List", "type": "object", @@ -37385,6 +38259,50 @@ "antivirus" ] }, + "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", @@ -39201,6 +40119,15 @@ }, "x-example": {} }, + "devKeys": { + "type": "array", + "description": "List of dev keys.", + "items": { + "type": "object", + "$ref": "#\/definitions\/devKey" + }, + "x-example": {} + }, "smtpEnabled": { "type": "boolean", "description": "Status for custom SMTP", @@ -39384,6 +40311,7 @@ "platforms", "webhooks", "keys", + "devKeys", "smtpEnabled", "smtpSenderName", "smtpSenderEmail", @@ -39574,6 +40502,65 @@ "sdks" ] }, + "devKey": { + "description": "DevKey", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Key ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Key creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Key update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Key name.", + "x-example": "Dev API Key" + }, + "expire": { + "type": "string", + "description": "Key expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "919c2d18fb5d4...a2ae413da83346ad2" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "sdks": { + "type": "array", + "description": "List of SDK user agents that used this key.", + "items": { + "type": "string" + }, + "x-example": "appwrite:flutter" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "expire", + "secret", + "accessedAt", + "sdks" + ] + }, "mockNumber": { "description": "Mock Number", "type": "object", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 41661b20ac..eb1e569678 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -8282,7 +8282,7 @@ }, "x-appwrite": { "method": "list", - "weight": 368, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -8354,7 +8354,7 @@ }, "x-appwrite": { "method": "create", - "weight": 365, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -8605,7 +8605,7 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 370, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -8656,7 +8656,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 371, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -8708,7 +8708,7 @@ }, "x-appwrite": { "method": "get", - "weight": 366, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -8767,7 +8767,7 @@ }, "x-appwrite": { "method": "update", - "weight": 367, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -9012,7 +9012,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 369, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -9073,7 +9073,7 @@ }, "x-appwrite": { "method": "updateFunctionDeployment", - "weight": 374, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9152,7 +9152,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 375, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -9232,7 +9232,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 372, + "weight": 377, "cookies": false, "type": "upload", "deprecated": false, @@ -9324,7 +9324,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 380, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -9409,7 +9409,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 377, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -9515,7 +9515,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 378, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -9613,7 +9613,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 373, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9675,7 +9675,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 376, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -9744,7 +9744,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 379, + "weight": 384, "cookies": false, "type": "location", "deprecated": false, @@ -9830,7 +9830,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 381, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -9899,7 +9899,7 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 384, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -9974,7 +9974,7 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 382, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -10094,7 +10094,7 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 383, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -10160,7 +10160,7 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 385, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10229,7 +10229,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 390, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -10288,7 +10288,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 388, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -10380,7 +10380,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 389, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -10447,7 +10447,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 391, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -10539,7 +10539,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 392, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -17154,7 +17154,7 @@ }, "x-appwrite": { "method": "list", - "weight": 397, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -17226,7 +17226,7 @@ }, "x-appwrite": { "method": "create", - "weight": 395, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -17492,7 +17492,7 @@ }, "x-appwrite": { "method": "listFrameworks", - "weight": 400, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17543,7 +17543,7 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 423, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -17595,7 +17595,7 @@ }, "x-appwrite": { "method": "get", - "weight": 396, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -17654,7 +17654,7 @@ }, "x-appwrite": { "method": "update", - "weight": 398, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -17913,7 +17913,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 399, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -17974,7 +17974,7 @@ }, "x-appwrite": { "method": "updateSiteDeployment", - "weight": 406, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -18053,7 +18053,7 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 405, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -18133,7 +18133,7 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 401, + "weight": 406, "cookies": false, "type": "upload", "deprecated": false, @@ -18233,7 +18233,7 @@ }, "x-appwrite": { "method": "createDuplicateDeployment", - "weight": 409, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -18312,7 +18312,7 @@ }, "x-appwrite": { "method": "createTemplateDeployment", - "weight": 402, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -18418,7 +18418,7 @@ }, "x-appwrite": { "method": "createVcsDeployment", - "weight": 403, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -18517,7 +18517,7 @@ }, "x-appwrite": { "method": "getDeployment", - "weight": 404, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -18579,7 +18579,7 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 407, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18648,7 +18648,7 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 408, + "weight": 413, "cookies": false, "type": "location", "deprecated": false, @@ -18734,7 +18734,7 @@ }, "x-appwrite": { "method": "updateDeploymentStatus", - "weight": 410, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18803,7 +18803,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 412, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -18876,7 +18876,7 @@ }, "x-appwrite": { "method": "getLog", - "weight": 411, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -18940,7 +18940,7 @@ }, "x-appwrite": { "method": "deleteLog", - "weight": 413, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -19009,7 +19009,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 416, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -19068,7 +19068,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 414, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -19160,7 +19160,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 415, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -19227,7 +19227,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 417, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -19319,7 +19319,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 418, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -21628,6 +21628,463 @@ ] } }, + "\/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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "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": "", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "", + "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": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "File token ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, "\/users": { "get": { "summary": "List users", @@ -25231,6 +25688,31 @@ "buckets" ] }, + "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", @@ -27822,6 +28304,50 @@ "antivirus" ] }, + "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", diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 20f64496ac..1deef8afdd 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -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) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) - ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('success', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey']) + ->param('failure', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey']) ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('request') ->inject('response') @@ -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) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) - ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('success', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey']) + ->param('failure', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey']) ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('request') ->inject('response') @@ -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) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey']) ->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true) ->inject('request') ->inject('response') @@ -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) => new Host($clients), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) + ->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients', 'devKey']) ->inject('request') ->inject('response') ->inject('user') @@ -3434,7 +3434,7 @@ App::post('/v1/account/verification') )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page + ->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients', 'devKey']) // TODO add built-in confirm page ->inject('request') ->inject('response') ->inject('project') diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 4a1e5de227..afb27b2c94 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -4,6 +4,7 @@ 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; @@ -27,8 +28,11 @@ 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; @@ -345,18 +349,50 @@ App::post('/v1/migrations/csv') throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); } - if (!empty($file->getAttribute('openSSLCipher')) || $file->getAttribute('algorithm', Compression::NONE) !== Compression::NONE) { - throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED, "Only uncompressed, unencrypted CSV files can be used for document import."); - } + // no encryption, compression on files above 20MB. + $hasEncryption = !empty($file->getAttribute('openSSLCipher')); + $compression = $file->getAttribute('algorithm', Compression::NONE); + $hasCompression = $compression !== Compression::NONE; - // copy to temporary folder $migrationId = ID::unique(); $newPath = $deviceForImports->getPath('/' . $migrationId . '_' . $fileId . '.csv'); - if (!$deviceForFiles->transfer($path, $newPath, $deviceForImports)) { + + 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($path); + $fileSize = $deviceForImports->getFileSize($newPath); $resources = Transfer::extractServices([Transfer::GROUP_DATABASES]); $migration = $dbForProject->createDocument('migrations', new Document([ diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index f13c9703c5..95927b380a 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -936,9 +936,10 @@ 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, 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, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal) { if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); @@ -953,19 +954,24 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (!$fileSecurity && !$valid) { + if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } - if ($fileSecurity && !$valid) { + if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -1765,6 +1771,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') $response->noContent(); }); +/** Storage usage */ App::get('/v1/storage/usage') ->desc('Get storage usage stats') ->groups(['api', 'storage']) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 3e0e366b6b..f58be39857 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -51,6 +51,7 @@ use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; use Utopia\Validator\Host; use Utopia\Validator\Text; +use Utopia\Validator\URL; use Utopia\Validator\WhiteList; App::post('/v1/teams') @@ -455,7 +456,7 @@ App::post('/v1/teams/:teamId/memberships') } return new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE); }, 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project']) - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) // TODO add our own built-in confirm page + ->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey']) // TODO add our own built-in confirm page ->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true) ->inject('response') ->inject('project') diff --git a/app/controllers/general.php b/app/controllers/general.php index 8985c82db6..ee0b6ca19f 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -106,7 +106,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw ); if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); + $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); @@ -760,8 +760,9 @@ App::init() ->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, ?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, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey) { /* * Appwrite Router */ @@ -994,6 +995,10 @@ 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 @@ -1004,6 +1009,7 @@ 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', '')) @@ -1027,8 +1033,9 @@ App::options() ->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, ?Key $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) { /* * Appwrite Router */ @@ -1052,6 +1059,10 @@ 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 */ @@ -1072,6 +1083,7 @@ 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(); @@ -1286,7 +1298,7 @@ App::error() $type = $error->getType(); - $output = ((App::isDevelopment())) ? [ + $output = App::isDevelopment() ? [ 'message' => $message, 'code' => $code, 'file' => $file, @@ -1543,11 +1555,12 @@ 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); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 957a7a7d23..429268203c 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -250,7 +250,7 @@ App::init() ); if ($dbKey) { - $accessedAt = $dbKey->getAttribute('accessedAt', ''); + $accessedAt = $dbKey->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { $dbKey->setAttribute('accessedAt', DateTime::now()); @@ -261,7 +261,7 @@ App::init() $sdkValidator = new WhiteList($servers, true); $sdk = $request->getHeader('x-sdk-name', 'UNKNOWN'); - if ($sdkValidator->isValid($sdk)) { + if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) { $sdks = $dbKey->getAttribute('sdks', []); if (!in_array($sdk, $sdks)) { @@ -311,7 +311,7 @@ App::init() // Update project last activity if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); + $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); @@ -320,7 +320,7 @@ App::init() // Update user last activity if (!empty($user->getId())) { - $accessedAt = $user->getAttribute('accessedAt', ''); + $accessedAt = $user->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) { $user->setAttribute('accessedAt', DateTime::now()); @@ -399,10 +399,12 @@ App::init() ->inject('queueForStatsUsage') ->inject('dbForProject') ->inject('timelimit') + ->inject('resourceToken') ->inject('mode') ->inject('apiKey') ->inject('plan') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, string $mode, ?Key $apiKey, array $plan) use ($usageDatabaseListener, $eventDatabaseListener) { + ->inject('devKey') + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); @@ -469,6 +471,7 @@ App::init() $enabled // Abuse is enabled && !$isAppUser // User is not API key && !$isPrivilegedUser // User is not an admin + && $devKey->isEmpty() // request doesn't not contain development key && $abuse->check() // Route is rate-limited ) { throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); @@ -552,6 +555,10 @@ App::init() $bucketId = $parts[1] ?? null; $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -559,20 +566,23 @@ App::init() $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - - if (!$fileSecurity && !$valid) { + if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } $parts = explode('/', $cacheLog->getAttribute('resource')); $fileId = $parts[1] ?? null; - if ($fileSecurity && !$valid) { + if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -798,7 +808,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', ''); + $accessedAt = $cacheLog->getAttribute('accessedAt', 0); $now = DateTime::now(); if ($cacheLog->isEmpty()) { Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 933f291c0d..f110fe1554 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -133,6 +133,20 @@ Database::addFilter( } ); +Database::addFilter( + 'subQueryDevKeys', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return $database + ->find('devKeys', [ + Query::equal('projectInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ]); + } +); + Database::addFilter( 'subQueryWebhooks', function (mixed $value) { diff --git a/app/init/resources.php b/app/init/resources.php index 1e6154df10..f4ccca3f26 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -29,6 +29,7 @@ use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; +use Utopia\Database\DateTime as DatabaseDateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; @@ -49,6 +50,7 @@ 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 @@ -789,6 +791,49 @@ App::setResource('smsRates', function () { return []; }); +App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform) { + $devKey = $request->getHeader('x-appwrite-dev-key', $request->getParam('devKey', '')); + + // Check if given key match project's development keys + $key = $project->find('secret', $devKey, 'devKeys'); + if (!$key) { + return new Document([]); + } + + // check expiration + $expire = $key->getAttribute('expire'); + if (!empty($expire) && $expire < DatabaseDateTime::formatTz(DatabaseDateTime::now())) { + return new Document([]); + } + + // update access time + $accessedAt = $key->getAttribute('accessedAt', 0); + if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { + $key->setAttribute('accessedAt', DatabaseDateTime::now()); + Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); + } + + // add sdk to key + $sdkValidator = new WhiteList($servers, true); + $sdk = $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') { @@ -852,3 +897,46 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key }, ['request', 'project']); App::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST'))); + +App::setResource('resourceToken', function ($project, $dbForProject, $request) { + $tokenJWT = $request->getParam('token'); + + if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication + $jwt = new JWT(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']); diff --git a/app/views/general/error.phtml b/app/views/general/error.phtml index 60afe86494..c6457ce98f 100644 --- a/app/views/general/error.phtml +++ b/app/views/general/error.phtml @@ -1,4 +1,6 @@ getParam('development', false); $type = $this->getParam('type', 'general_server_error'); $code = $this->getParam('code', 500); @@ -12,6 +14,15 @@ $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'; @@ -94,6 +105,8 @@ switch ($type) { + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index f8f7b9ac6c..9eae11538b 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -318,6 +318,10 @@ 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 = []; diff --git a/src/Appwrite/Platform/Appwrite.php b/src/Appwrite/Platform/Appwrite.php index be6ddbae8a..ae3d4d6646 100644 --- a/src/Appwrite/Platform/Appwrite.php +++ b/src/Appwrite/Platform/Appwrite.php @@ -5,8 +5,10 @@ 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 @@ -14,9 +16,11 @@ 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()); } } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php new file mode 100644 index 0000000000..9636a166c1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php @@ -0,0 +1,96 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/projects/:projectId/dev-keys') + ->desc('Create dev key') + ->groups(['api', 'projects']) + ->label('scope', 'projects.write') + ->label('sdk', new Method( + namespace: 'projects', + name: 'createDevKey', + description: <<param('projectId', '', new UID(), 'Project unique ID.') + ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') + ->param('expire', null, new DatetimeValidator(), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.', false) + ->inject('user') + ->inject('response') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action(string $projectId, string $name, ?string $expire, Document $user, Response $response, Database $dbForPlatform) + { + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + $devKeyId = ID::unique(); + $key = new Document([ + '$id' => $devKeyId, + '$permissions' => [ + Permission::read(Role::user($user->getId())), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], + 'projectInternalId' => $project->getInternalId(), + 'projectId' => $project->getId(), + 'name' => $name, + 'expire' => $expire, + 'sdks' => [], + 'search' => implode('', [$name, $project->getId(), $devKeyId]), + 'accessedAt' => null, + 'secret' => \bin2hex(\random_bytes(128)), + ]); + + $key = $dbForPlatform->createDocument('devKeys', $key); + + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($key, Response::MODEL_DEV_KEY); + } +} diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php new file mode 100644 index 0000000000..3adf26f816 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php @@ -0,0 +1,75 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/projects/:projectId/dev-keys/:keyId') + ->desc('Delete dev key') + ->groups(['api', 'projects']) + ->label('scope', 'projects.write') + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteDevKey', + description: <<param('projectId', '', new UID(), 'Project unique ID.') + ->param('keyId', '', new UID(), 'Key unique ID.') + ->inject('response') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action(string $projectId, string $keyId, Response $response, Database $dbForPlatform) + { + + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + $key = $dbForPlatform->getDocument('devKeys', $keyId); + + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { + throw new Exception(Exception::KEY_NOT_FOUND); + } + + $dbForPlatform->deleteDocument('devKeys', $key->getId()); + + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php new file mode 100644 index 0000000000..c933c5be93 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php @@ -0,0 +1,71 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/projects/:projectId/dev-keys/:keyId') + ->desc('Get dev key') + ->groups(['api', 'projects']) + ->label('scope', 'projects.read') + ->label('sdk', new Method( + namespace: 'projects', + name: 'getDevKey', + description: <<param('projectId', '', new UID(), 'Project unique ID.') + ->param('keyId', '', new UID(), 'Key unique ID.') + ->inject('response') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action(string $projectId, string $keyId, Response $response, Database $dbForPlatform) + { + + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + $key = $dbForPlatform->getDocument('devKeys', $keyId); + + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { + throw new Exception(Exception::KEY_NOT_FOUND); + } + + $response->dynamic($key, Response::MODEL_DEV_KEY); + } +} diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php new file mode 100644 index 0000000000..c556578bc2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php @@ -0,0 +1,82 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/projects/:projectId/dev-keys/:keyId') + ->desc('Update dev key') + ->groups(['api', 'projects']) + ->label('scope', 'projects.write') + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateDevKey', + description: <<param('projectId', '', new UID(), 'Project unique ID.') + ->param('keyId', '', new UID(), 'Key unique ID.') + ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') + ->param('expire', null, new DatetimeValidator(), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.') + ->inject('response') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + public function action(string $projectId, string $keyId, string $name, ?string $expire, Response $response, Database $dbForPlatform) + { + + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + $key = $dbForPlatform->getDocument('devKeys', $keyId); + + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { + throw new Exception(Exception::KEY_NOT_FOUND); + } + + $key + ->setAttribute('name', $name) + ->setAttribute('expire', $expire) + ->setAttribute('search', implode('', [$name, $project->getId(), $key->getId()])); + + $dbForPlatform->updateDocument('devKeys', $key->getId(), $key); + + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); + + $response->dynamic($key, Response::MODEL_DEV_KEY); + } +} diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php new file mode 100644 index 0000000000..0d3516558e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php @@ -0,0 +1,88 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/projects/:projectId/dev-keys') + ->desc('List dev keys') + ->groups(['api', 'projects']) + ->label('scope', 'projects.read') + ->label('sdk', new Method( + namespace: 'projects', + name: 'listDevKeys', + description: <<param('projectId', '', new UID(), 'Project unique ID.') + ->param('queries', [], new DevKeys(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', DevKeys::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->inject('response') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action(string $projectId, ?array $queries, ?string $search, Response $response, Database $dbForPlatform) + { + + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); + + $keys = $dbForPlatform->find('devKeys', $queries); + + $response->dynamic(new Document([ + 'devKeys' => $keys, + 'total' => count($keys), + ]), Response::MODEL_DEV_KEY_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Projects/Module.php b/src/Appwrite/Platform/Modules/Projects/Module.php new file mode 100644 index 0000000000..2a550acf54 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Projects/Module.php @@ -0,0 +1,14 @@ +addService('http', new Http()); + } +} diff --git a/src/Appwrite/Platform/Modules/Projects/Services/Http.php b/src/Appwrite/Platform/Modules/Projects/Services/Http.php new file mode 100644 index 0000000000..cec8ed6d16 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Projects/Services/Http.php @@ -0,0 +1,23 @@ +type = Service::TYPE_HTTP; + $this->addAction(CreateDevKey::getName(), new CreateDevKey()); + $this->addAction(UpdateDevKey::getName(), new UpdateDevKey()); + $this->addAction(GetDevKey::getName(), new GetDevKey()); + $this->addAction(ListDevKeys::getName(), new ListDevKeys()); + $this->addAction(DeleteDevKey::getName(), new DeleteDevKey()); + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/Action.php new file mode 100644 index 0000000000..aec665f406 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/Action.php @@ -0,0 +1,45 @@ + $dbForProject->getDocument('buckets', $bucketId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); + } + + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); + if (!$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + + $fileSecurity = $bucket->getAttribute('fileSecurity', false); + if ($fileSecurity) { + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + } else { + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + } + + if ($file->isEmpty()) { + throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); + } + return [ + 'bucket' => $bucket, + 'file' => $file, + ]; + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/Create.php new file mode 100644 index 0000000000..76e161e101 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/Create.php @@ -0,0 +1,116 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/tokens/buckets/:bucketId/files/:fileId') + ->desc('Create file token') + ->groups(['api', 'token']) + ->label('scope', 'tokens.write') + ->label('event', 'tokens.[tokenId].create') + ->label('audits.event', 'token.create') + ->label('audits.resource', 'token/{response.$id}') + ->label('usage.metric', 'tokens.{scope}.requests.create') + ->label('usage.params', ['resourceId:{request.resourceId}', 'resourceType:{request.resourceType}']) + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'tokens', + name: 'createFileToken', + description: <<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 unique ID.') + ->param('expire', null, new Nullable(new DatetimeValidator()), 'Token expiry date', true) + ->param('permissions', [], new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('response') + ->inject('dbForProject') + ->inject('user') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $bucketId, string $fileId, ?string $expire, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents) + { + + /** + * @var Document $bucket + * @var Document $file + */ + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); + + $fileSecurity = $bucket->getAttribute('fileSecurity', false); + $validator = new Authorization(Database::PERMISSION_UPDATE); + $bucketPermission = $validator->isValid($bucket->getUpdate()); + + if ($fileSecurity) { + $filePermission = $validator->isValid($file->getUpdate()); + if (!$bucketPermission && !$filePermission) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + } elseif (!$bucketPermission) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + + $token = $dbForProject->createDocument('resourceTokens', new Document([ + '$id' => ID::unique(), + 'secret' => Auth::tokenGenerator(128), + 'resourceId' => $bucketId . ':' . $fileId, + 'resourceInternalId' => $bucket->getInternalId() . ':' . $file->getInternalId(), + 'resourceType' => 'files', + 'expire' => $expire, + '$permissions' => $permissions + ])); + + $queueForEvents + ->setParam('bucketId', $bucket->getId()) + ->setParam('fileId', $file->getId()) + ->setParam('tokenId', $token->getId()) + ->setContext('bucket', $bucket) + ; + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($token, Response::MODEL_RESOURCE_TOKEN); + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/XList.php new file mode 100644 index 0000000000..aa2637b1d1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Buckets/Files/XList.php @@ -0,0 +1,91 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/tokens/buckets/:bucketId/files/:fileId') + ->desc('List tokens') + ->groups(['api', 'tokens']) + ->label('scope', 'tokens.read') + ->label('usage.metric', 'tokens.requests.read') + ->label('sdk', new Method( + namespace: 'tokens', + name: 'list', + description: <<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 unique ID.') + ->param('queries', [], new FileTokens(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', FileTokens::ALLOWED_ATTRIBUTES), true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $bucketId, string $fileId, array $queries, Response $response, Database $dbForProject) + { + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); + + $queries = Query::parseQueries($queries); + $queries[] = Query::equal('resourceType', ["files"]); + $queries[] = Query::equal('resourceId', [$bucket->getInternalId() . ':' . $file->getInternalId()]); + // Get cursor document if there was a cursor query + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + if ($cursor) { + /** @var Query $cursor */ + $tokenId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('resourceTokens', $tokenId); + + if ($cursorDocument->isEmpty()) { + throw new Exception(ExtendException::GENERAL_CURSOR_NOT_FOUND, "File token '{$tokenId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + $response->dynamic(new Document([ + 'tokens' => $dbForProject->find('resourceTokens', $queries), + 'total' => $dbForProject->count('resourceTokens', $filterQueries, APP_LIMIT_COUNT), + ]), Response::MODEL_RESOURCE_TOKEN_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Delete.php b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Delete.php new file mode 100644 index 0000000000..bde45b8e1f --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Delete.php @@ -0,0 +1,79 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/tokens/:tokenId') + ->desc('Delete token') + ->groups(['api', 'tokens']) + ->label('scope', 'tokens.write') + ->label('event', 'tokens.[tokenId].delete') + ->label('audits.event', 'tokens.delete') + ->label('audits.resource', 'token/{request.tokenId}') + ->label('usage.metric', 'tokens.{scope}.requests.delete') + ->label('usage.params', ['tokenId:{request.tokenId}']) + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'tokens', + name: 'delete', + description: <<param('tokenId', '', new UID(), 'Token ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $tokenId, Response $response, Database $dbForProject, Event $queueForEvents) + { + $token = $dbForProject->getDocument('resourceTokens', $tokenId); + if ($token->isEmpty()) { + throw new Exception(Exception::TOKEN_NOT_FOUND); + } + + $dbForProject->deleteDocument('resourceTokens', $tokenId); + + $queueForEvents + ->setParam('tokenId', $token->getId()) + ->setPayload($response->output($token, Response::MODEL_RESOURCE_TOKEN)) + ; + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Get.php new file mode 100644 index 0000000000..2d920a5ea9 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Get.php @@ -0,0 +1,65 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/tokens/:tokenId') + ->desc('Get token') + ->groups(['api', 'tokens']) + ->label('scope', 'tokens.read') + ->label('usage.metric', 'tokens.{scope}.requests.read') + ->label('usage.params', ['tokenId:{request.tokenId}']) + ->label('sdk', new Method( + namespace: 'tokens', + name: 'get', + description: <<param('tokenId', '', new UID(), 'Token ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $tokenId, Response $response, Database $dbForProject) + { + $token = $dbForProject->getDocument('resourceTokens', $tokenId); + + if ($token->isEmpty()) { + throw new Exception(Exception::TOKEN_NOT_FOUND); + } + + $response->dynamic($token, Response::MODEL_RESOURCE_TOKEN); + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Tokens/JWT/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/JWT/Get.php new file mode 100644 index 0000000000..f209908878 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/JWT/Get.php @@ -0,0 +1,90 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/tokens/:tokenId/jwt') + ->desc('Get token as JWT') + ->groups(['api', 'tokens']) + ->label('scope', 'tokens.read') + ->label('usage.metric', 'tokens.{scope}.requests.read') + ->label('usage.params', ['tokenId:{request.tokenId}']) + ->label('sdk', new Method( + namespace: 'tokens', + name: 'getJWT', + description: <<param('tokenId', '', new UID(), 'File token ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $tokenId, Response $response, Database $dbForProject) + { + $token = $dbForProject->getDocument('resourceTokens', $tokenId); + + if ($token->isEmpty()) { + throw new Exception(Exception::TOKEN_NOT_FOUND); + } + + // calculate maxAge based on expiry date + $maxAge = PHP_INT_MAX; + $expire = $token->getAttribute('expire'); + if ($expire !== null) { + $now = new \DateTime(); + $expiryDate = new \DateTime($expire); + if ($expiryDate < $now) { + throw new Exception(Exception::TOKEN_EXPIRED); + } + $maxAge = $expiryDate->getTimestamp() - $now->getTimestamp(); + } + + $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $maxAge, 10); // Instantiate with key, algo, maxAge and leeway. + + $response + ->setStatusCode(Response::STATUS_CODE_OK) + ->dynamic(new Document(['jwt' => $jwt->encode([ + 'resourceType' => $token->getAttribute('resourceType'), + 'resourceId' => $token->getAttribute('resourceId'), + 'resourceInternalId' => $token->getAttribute('resourceInternalId'), + 'tokenId' => $token->getId(), + 'secret' => $token->getAttribute('secret') + ])]), Response::MODEL_JWT); + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Update.php b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Update.php new file mode 100644 index 0000000000..fbf9a40996 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Http/Tokens/Update.php @@ -0,0 +1,124 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/tokens/:tokenId') + ->desc('Update token') + ->groups(['api', 'tokens']) + ->label('scope', 'tokens.write') + ->label('event', 'tokens.[tokenId].update') + ->label('audits.event', 'tokens.update') + ->label('audits.resource', 'tokens/{response.$id}') + ->label('usage.metric', 'tokens.{scope}.requests.update') + ->label('usage.params', ['tokenId:{request.tokenId}']) + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'tokens', + name: 'update', + description: <<param('tokenId', '', new UID(), 'Token unique ID.') + ->param('expire', null, new Nullable(new DatetimeValidator()), 'File token expiry date', true) + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $tokenId, ?string $expire, ?array $permissions, Response $response, Database $dbForProject, Event $queueForEvents) + { + $token = $dbForProject->getDocument('resourceTokens', $tokenId); + + if ($token->isEmpty()) { + throw new Exception(Exception::TOKEN_NOT_FOUND); + } + + // Map aggregate permissions into the multiple permissions they represent. + $permissions = Permission::aggregate($permissions, [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]); + + // Users can only manage their own roles, API keys and Admin users can manage any + $roles = Authorization::getRoles(); + if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + } + } + } + } + + if (\is_null($permissions)) { + $permissions = $token->getPermissions() ?? []; + } + + $token + ->setAttribute('expire', $expire) + ->setAttribute('$permissions', $permissions); + + $token = $dbForProject->updateDocument('resourceTokens', $tokenId, $token); + + $queueForEvents + ->setParam('tokenId', $token->getId()) + ; + + $response->dynamic($token, Response::MODEL_RESOURCE_TOKEN); + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Module.php b/src/Appwrite/Platform/Modules/Storage/Module.php new file mode 100644 index 0000000000..59eb9e87a6 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Module.php @@ -0,0 +1,14 @@ +addService('http', new Http()); + } +} diff --git a/src/Appwrite/Platform/Modules/Storage/Services/Http.php b/src/Appwrite/Platform/Modules/Storage/Services/Http.php new file mode 100644 index 0000000000..5fe4d096b3 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Storage/Services/Http.php @@ -0,0 +1,28 @@ +type = Service::TYPE_HTTP; + $this + ->addAction(CreateFileToken::getName(), new CreateFileToken()) + ->addAction(GetToken::getName(), new GetToken()) + ->addAction(GetTokenJWT::getName(), new GetTokenJWT()) + ->addAction(ListFileTokens::getName(), new ListFileTokens()) + ->addAction(UpdateToken::getName(), new UpdateToken()) + ->addAction(DeleteToken::getName(), new DeleteToken()) + ; + + } +} diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 303e03cb8c..88f98fa76a 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -43,7 +43,7 @@ abstract class ScheduleBase extends Action protected function updateProjectAccess(Document $project, Database $dbForPlatform): void { if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); + $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index b009da0718..27d42fe6d9 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -216,7 +216,10 @@ class Migrations extends Action 'databases.read', 'collections.read', 'documents.read', - ], + 'documents.write', + 'tokens.read', + 'tokens.write', + ] ]); return API_KEY_DYNAMIC . '_' . $apiKey; diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/DevKeys.php b/src/Appwrite/Utopia/Database/Validator/Queries/DevKeys.php new file mode 100644 index 0000000000..d9dbbeadc4 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/DevKeys.php @@ -0,0 +1,20 @@ +setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG)) ->setModel(new BaseList('Files List', self::MODEL_FILE_LIST, 'files', self::MODEL_FILE)) ->setModel(new BaseList('Buckets List', self::MODEL_BUCKET_LIST, 'buckets', self::MODEL_BUCKET)) + ->setModel(new BaseList('Resource Tokens List', self::MODEL_RESOURCE_TOKEN_LIST, 'tokens', self::MODEL_RESOURCE_TOKEN)) ->setModel(new BaseList('Teams List', self::MODEL_TEAM_LIST, 'teams', self::MODEL_TEAM)) ->setModel(new BaseList('Memberships List', self::MODEL_MEMBERSHIP_LIST, 'memberships', self::MODEL_MEMBERSHIP)) ->setModel(new BaseList('Sites List', self::MODEL_SITE_LIST, 'sites', self::MODEL_SITE)) @@ -390,6 +397,7 @@ class Response extends SwooleResponse ->setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT, true, false)) ->setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK, true, false)) ->setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY, true, false)) + ->setModel(new BaseList('Dev Keys List', self::MODEL_DEV_KEY_LIST, 'devKeys', self::MODEL_DEV_KEY, true, false)) ->setModel(new BaseList('Auth Providers List', self::MODEL_AUTH_PROVIDER_LIST, 'platforms', self::MODEL_AUTH_PROVIDER, true, false)) ->setModel(new BaseList('Platforms List', self::MODEL_PLATFORM_LIST, 'platforms', self::MODEL_PLATFORM, true, false)) ->setModel(new BaseList('Countries List', self::MODEL_COUNTRY_LIST, 'countries', self::MODEL_COUNTRY)) @@ -447,6 +455,7 @@ class Response extends SwooleResponse ->setModel(new LocaleCode()) ->setModel(new File()) ->setModel(new Bucket()) + ->setModel(new ResourceToken()) ->setModel(new Team()) ->setModel(new Membership()) ->setModel(new Site()) @@ -472,6 +481,7 @@ class Response extends SwooleResponse ->setModel(new Project()) ->setModel(new Webhook()) ->setModel(new Key()) + ->setModel(new DevKey()) ->setModel(new MockNumber()) ->setModel(new AuthProvider()) ->setModel(new Platform()) diff --git a/src/Appwrite/Utopia/Response/Model/DevKey.php b/src/Appwrite/Utopia/Response/Model/DevKey.php new file mode 100644 index 0000000000..b8da6c0cfc --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/DevKey.php @@ -0,0 +1,89 @@ +addRule('$id', [ + 'type' => self::TYPE_STRING, + 'description' => 'Key ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Key creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Key update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Key name.', + 'default' => '', + 'example' => 'Dev API Key', + ]) + ->addRule('expire', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Key expiration date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('secret', [ + 'type' => self::TYPE_STRING, + 'description' => 'Secret key.', + 'default' => '', + 'example' => '919c2d18fb5d4...a2ae413da83346ad2', + ]) + ->addRule('accessedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after ' . APP_KEY_ACCESS / 60 / 60 . ' hours.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE + ]) + ->addRule('sdks', [ + 'type' => self::TYPE_STRING, + 'description' => 'List of SDK user agents that used this key.', + 'default' => null, + 'example' => 'appwrite:flutter', + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'DevKey'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_DEV_KEY; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Project.php b/src/Appwrite/Utopia/Response/Model/Project.php index fbbe062531..efd002654e 100644 --- a/src/Appwrite/Utopia/Response/Model/Project.php +++ b/src/Appwrite/Utopia/Response/Model/Project.php @@ -197,6 +197,13 @@ class Project extends Model 'example' => new \stdClass(), 'array' => true, ]) + ->addRule('devKeys', [ + 'type' => Response::MODEL_DEV_KEY, + 'description' => 'List of dev keys.', + 'default' => [], + 'example' => new \stdClass(), + 'array' => true, + ]) ->addRule('smtpEnabled', [ 'type' => self::TYPE_BOOLEAN, 'description' => 'Status for custom SMTP', diff --git a/src/Appwrite/Utopia/Response/Model/ResourceToken.php b/src/Appwrite/Utopia/Response/Model/ResourceToken.php new file mode 100644 index 0000000000..8f44a55b56 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/ResourceToken.php @@ -0,0 +1,71 @@ +addRule('$id', [ + 'type' => self::TYPE_STRING, + 'description' => 'Token ID.', + 'default' => '', + 'example' => 'bb8ea5c16897e', + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Token creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('resourceId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Resource ID.', + 'default' => '', + 'example' => '5e5ea5c168bb8:5e5ea5c168bb8', + ]) + ->addRule('resourceInternalId', [ + 'type' => self::TYPE_STRING, + 'description' => 'File ID.', + 'default' => '', + 'example' => '1:1', + ]) + ->addRule('resourceType', [ + 'type' => self::TYPE_STRING, + 'description' => 'Resource type.', + 'default' => '', + 'example' => 'file', + ]) + ->addRule('expire', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Token expiration date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'ResourceToken'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_RESOURCE_TOKEN; + } +} diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index a1616f2f74..a354696f53 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -3,6 +3,7 @@ namespace Tests\E2E\Scopes; use Tests\E2E\Client; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\System\System; @@ -102,7 +103,9 @@ trait ProjectCustom 'subscribers.write', 'subscribers.read', 'migrations.write', - 'migrations.read' + 'migrations.read', + 'tokens.read', + 'tokens.write', ], ]); @@ -110,6 +113,19 @@ trait ProjectCustom $this->assertNotEmpty($key['body']); $this->assertNotEmpty($key['body']['secret']); + $devKey = $this->client->call(Client::METHOD_POST, '/projects/' . $project['body']['$id'] . '/dev-keys', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'name' => 'Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 3600), + ]); + $this->assertEquals(201, $devKey['headers']['status-code']); + $this->assertNotEmpty($devKey['body']); + $this->assertNotEmpty($devKey['body']['secret']); + $webhook = $this->client->call(Client::METHOD_POST, '/projects/' . $project['body']['$id'] . '/webhooks', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', @@ -150,9 +166,11 @@ trait ProjectCustom '$id' => $project['body']['$id'], 'name' => $project['body']['name'], 'apiKey' => $key['body']['secret'], + 'devKey' => $devKey['body']['secret'], 'webhookId' => $webhook['body']['$id'], 'signatureKey' => $webhook['body']['signatureKey'], ]; + if ($fresh) { return $project; } diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 3213ff4c5d..6deaa62c05 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -56,7 +56,7 @@ abstract class Scope extends TestCase /** * @return array */ - abstract public function getHeaders(): array; + abstract public function getHeaders(bool $devKey = true): array; /** * @return array diff --git a/tests/e2e/Scopes/SideClient.php b/tests/e2e/Scopes/SideClient.php index 54f77a9747..17ee7a3002 100644 --- a/tests/e2e/Scopes/SideClient.php +++ b/tests/e2e/Scopes/SideClient.php @@ -4,12 +4,17 @@ namespace Tests\E2E\Scopes; trait SideClient { - public function getHeaders(): array + public function getHeaders(bool $devKey = true): array { - return [ + $headers = [ 'origin' => 'http://localhost', 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $this->getUser()['session'], + ]; + if ($devKey && isset($this->getProject()['devKey'])) { + $headers['x-appwrite-dev-key'] = $this->getProject()['devKey']; + } + return $headers; } /** diff --git a/tests/e2e/Scopes/SideConsole.php b/tests/e2e/Scopes/SideConsole.php index 74a0dd0c60..9ad3e93d6a 100644 --- a/tests/e2e/Scopes/SideConsole.php +++ b/tests/e2e/Scopes/SideConsole.php @@ -4,7 +4,7 @@ namespace Tests\E2E\Scopes; trait SideConsole { - public function getHeaders(): array + public function getHeaders(bool $devKey = true): array { return [ 'origin' => 'http://localhost', diff --git a/tests/e2e/Scopes/SideNone.php b/tests/e2e/Scopes/SideNone.php index 79c52afe00..1660beb777 100644 --- a/tests/e2e/Scopes/SideNone.php +++ b/tests/e2e/Scopes/SideNone.php @@ -4,7 +4,7 @@ namespace Tests\E2E\Scopes; trait SideNone { - public function getHeaders(): array + public function getHeaders(bool $devKey = true): array { return []; } diff --git a/tests/e2e/Scopes/SideServer.php b/tests/e2e/Scopes/SideServer.php index b5e15150e9..d27b2092b0 100644 --- a/tests/e2e/Scopes/SideServer.php +++ b/tests/e2e/Scopes/SideServer.php @@ -9,7 +9,7 @@ trait SideServer */ protected $key = []; - public function getHeaders(): array + public function getHeaders(bool $devKey = false): array { return [ 'x-appwrite-key' => $this->getProject()['apiKey'] diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 2d72625121..1a77cccb18 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -99,6 +99,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-dev-key' => $this->getProject()['devKey'] ?? '', ]), [ 'userId' => ID::unique(), 'email' => '', @@ -112,13 +113,14 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-dev-key' => $this->getProject()['devKey'] ?? '' ]), [ 'userId' => ID::unique(), 'email' => 'shortpass@appwrite.io', 'password' => $shortPassword ]); - $this->assertEquals($response['headers']['status-code'], 400); + $this->assertEquals(400, $response['headers']['status-code']); $longPassword = ''; for ($i = 0; $i < 257; $i++) { // 256 is the limit @@ -129,13 +131,14 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-dev-key' => $this->getProject()['devKey'] ?? '' ]), [ 'userId' => ID::unique(), 'email' => 'longpass@appwrite.io', 'password' => $longPassword, ]); - $this->assertEquals($response['headers']['status-code'], 400); + $this->assertEquals(400, $response['headers']['status-code']); return [ 'id' => $id, @@ -156,7 +159,7 @@ trait AccountBase 'email' => 'otpuser@appwrite.io' ]); - $this->assertEquals($response['headers']['status-code'], 201); + $this->assertEquals(201, $response['headers']['status-code'], ); $this->assertNotEmpty($response['body']['$id']); $this->assertNotEmpty($response['body']['$createdAt']); $this->assertNotEmpty($response['body']['userId']); @@ -286,6 +289,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-dev-key' => $this->getProject()['devKey'] ?? '' ]), [ 'userId' => ID::unique(), 'email' => $email, diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index daa5bcbff8..452b725c11 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -619,6 +619,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-dev-key' => $this->getProject()['devKey'] ?? '' ]), [ 'userId' => ID::unique(), 'email' => $data['email'], @@ -1217,6 +1218,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-dev-key' => $this->getProject()['devKey'] ?? '' ]), [ 'userId' => ID::unique(), 'email' => $email, diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsScope.php b/tests/e2e/Services/Databases/DatabasesPermissionsScope.php index 336e47db08..0042d253ac 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsScope.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsScope.php @@ -15,6 +15,7 @@ trait DatabasesPermissionsScope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-dev-key' => $this->getProject()['devKey'] ?? '', ], [ 'userId' => $id, 'email' => $email, diff --git a/tests/e2e/Services/GraphQL/AbuseTest.php b/tests/e2e/Services/GraphQL/AbuseTest.php index d4e87cf029..ea97492c2b 100644 --- a/tests/e2e/Services/GraphQL/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/AbuseTest.php @@ -88,7 +88,7 @@ class AbuseTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - ], $this->getHeaders()), $graphQLPayload); + ], $this->getHeaders(false)), $graphQLPayload); $max = System::getEnv('_APP_GRAPHQL_MAX_QUERY_COMPLEXITY', 250); diff --git a/tests/e2e/Services/Migrations/MigrationsBase.php b/tests/e2e/Services/Migrations/MigrationsBase.php index 45b57d6b0c..c241b38e3d 100644 --- a/tests/e2e/Services/Migrations/MigrationsBase.php +++ b/tests/e2e/Services/Migrations/MigrationsBase.php @@ -971,7 +971,6 @@ trait MigrationsBase $this->assertEquals($response['body']['required'], true); // make a bucket, upload a file to it! - // 1. enable compression, encryption $bucketOne = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -989,33 +988,11 @@ trait MigrationsBase $bucketOneId = $bucketOne['body']['$id']; - // 2. no compression and encryption - $bucketTwo = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ], [ - 'bucketId' => ID::unique(), - 'name' => 'Test Bucket 2', - 'maximumFileSize' => 2000000, //2MB - 'allowedFileExtensions' => ['csv'], - 'compression' => 'none', - 'encryption' => false - ]); - - $this->assertNotEmpty($bucketTwo['body']['$id']); - $this->assertEquals(201, $bucketTwo['headers']['status-code']); - - $bucketTwoId = $bucketTwo['body']['$id']; - $bucketIds = [ - 'compressed' => $bucketOneId, - 'uncompressed' => $bucketTwoId, - - // in uncompressed buckets! - 'missing-row' => $bucketTwoId, - 'missing-column' => $bucketTwoId, - 'irrelevant-column' => $bucketTwoId, + 'default' => $bucketOneId, + 'missing-row' => $bucketOneId, + 'missing-column' => $bucketOneId, + 'irrelevant-column' => $bucketOneId, ]; $fileIds = []; @@ -1049,20 +1026,6 @@ trait MigrationsBase $fileIds[$label] = $response['body']['$id']; } - // compressed, fail. - $compressed = $this->performCsvMigration( - [ - 'fileId' => $fileIds['compressed'], - 'bucketId' => $bucketIds['compressed'], - 'resourceId' => $databaseId . ':' . $collectionId, - ] - ); - - // fail on compressed, encrypted buckets! - $this->assertEquals(400, $compressed['body']['code']); - $this->assertEquals('storage_file_type_unsupported', $compressed['body']['type']); - $this->assertEquals('Only uncompressed, unencrypted CSV files can be used for document import.', $compressed['body']['message']); - // missing attribute, fail in worker. $missingColumn = $this->performCsvMigration( [ @@ -1150,12 +1113,12 @@ trait MigrationsBase ); }, 60000, 500); - // no compression, no encryption, pass. + // all data exists, pass/ $migration = $this->performCsvMigration( [ 'endpoint' => 'http://localhost/v1', - 'fileId' => $fileIds['uncompressed'], - 'bucketId' => $bucketIds['uncompressed'], + 'fileId' => $fileIds['default'], + 'bucketId' => $bucketIds['default'], 'resourceId' => $databaseId . ':' . $collectionId, ] ); diff --git a/tests/e2e/Services/Projects/ProjectsBase.php b/tests/e2e/Services/Projects/ProjectsBase.php index 53d9626252..0d1d6a5a44 100644 --- a/tests/e2e/Services/Projects/ProjectsBase.php +++ b/tests/e2e/Services/Projects/ProjectsBase.php @@ -2,6 +2,48 @@ namespace Tests\E2E\Services\Projects; +use Tests\E2E\Client; +use Utopia\Database\Helpers\ID; + trait ProjectsBase { + protected function setupProject(mixed $params): string + { + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => ID::unique(), + 'name' => 'Project Test', + ]); + + $this->assertEquals(201, $team['headers']['status-code'], 'Setup team failed with status code: ' . $team['headers']['status-code'] . ' and response: ' . json_encode($team['body'], JSON_PRETTY_PRINT)); + + $project = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + ...$params, + 'teamId' => $team['body']['$id'], + ]); + + $this->assertEquals(201, $project['headers']['status-code'], 'Setup project failed with status code: ' . $project['headers']['status-code'] . ' and response: ' . json_encode($project['body'], JSON_PRETTY_PRINT)); + + return $project['body']['$id']; + } + + protected function setupDevKey(mixed $params): array + { + $devKey = $this->client->call(Client::METHOD_POST, '/projects/' . $params['projectId'] . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + $this->assertEquals(201, $devKey['headers']['status-code'], 'Setup devKey failed with status code: ' . $devKey['headers']['status-code'] . ' and response: ' . json_encode($devKey['body'], JSON_PRETTY_PRINT)); + + return [ + '$id' => $devKey['body']['$id'], + 'secret' => $devKey['body']['secret'], + ]; + } } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index afd1189496..c4a0975f06 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -24,6 +24,7 @@ class ProjectsConsoleClientTest extends Scope use Async; /** + * @group devKeys * @group smtpAndTemplates * @group projectsCRUD */ public function testCreateProject(): array @@ -4255,4 +4256,611 @@ class ProjectsConsoleClientTest extends Scope return $data; } + + /** + * Devkeys Tests starts here ------------------------------------------------ + */ + + /** + * @group devKeys + */ + public function testCreateProjectDevKey(): void + { + /** + * Test for SUCCESS + */ + $id = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testCreateProjectDevKey', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals('Key Test', $response['body']['name']); + $this->assertNotEmpty($response['body']['secret']); + $this->assertArrayHasKey('accessedAt', $response['body']); + $this->assertEmpty($response['body']['accessedAt']); + + /** Create a second dev key */ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals('Dev Key Test', $response['body']['name']); + $this->assertNotEmpty($response['body']['secret']); + $this->assertArrayHasKey('accessedAt', $response['body']); + $this->assertEmpty($response['body']['accessedAt']); + + /** + * Test for FAILURE + */ + + /** TEST expiry date is required */ + $res = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test' + ]); + + $this->assertEquals(400, $res['headers']['status-code']); + } + + + /** + * @group devKeys + */ + public function testListProjectDevKey(): void + { + /** + * Test for SUCCESS + */ + $projectId = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testListProjectDevKey', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + /** Create devKey 1 */ + $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + /** Create devKey 2 */ + $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + /** List all dev keys */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(2, $response['body']['total']); + + /** List dev keys with limit */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::limit(1)->toString() + ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['total']); + + /** List dev keys with search */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'Dev' + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['total']); + $this->assertEquals('Dev Key Test', $response['body']['devKeys'][0]['name']); + + /** List dev keys with querying `expire` */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::lessThan('expire', (new \DateTime())->format('Y-m-d H:i:s'))->toString()] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(0, $response['body']['total']); // No dev keys expired + + /** + * Test for FAILURE + */ + + /** Test for search with invalid query */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::search('name', 'Invalid')->toString() + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('Invalid `queries` param: Invalid query: Attribute not found in schema: name', $response['body']['message']); + } + + + /** + * @group devKeys + */ + public function testGetProjectDevKey(): void + { + /** + * Test for SUCCESS + */ + $projectId = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testGetProjectDevKey', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $devKey = $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals($devKey['$id'], $response['body']['$id']); + $this->assertEquals('Dev Key Test', $response['body']['name']); + $this->assertNotEmpty($response['body']['secret']); + $this->assertArrayHasKey('accessedAt', $response['body']); + $this->assertEmpty($response['body']['accessedAt']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/error', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * @group devKeys + */ + public function testGetDevKeyWithSdks(): void + { + /** + * Test for SUCCESS + */ + $projectId = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testGetDevKeyWithSdks', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $devKey = $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + /** Use dev key with python sdk */ + $res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'], + 'x-sdk-name' => 'python' + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(401, $res['headers']['status-code']); + + /** Use dev key with php sdk */ + $res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'], + 'x-sdk-name' => 'php' + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(401, $res['headers']['status-code']); + + /** Get the dev key */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertArrayHasKey('sdks', $response['body']); + $this->assertCount(2, $response['body']['sdks']); + $this->assertContains('python', $response['body']['sdks']); + $this->assertContains('php', $response['body']['sdks']); + } + + /** + * @group devKeys + */ + public function testNoHostValidationWithDevKey(): void + { + /** + * Test for SUCCESS + */ + $projectId = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testNoHostValidationWithDevKey', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $devKey = $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + $provider = 'mock'; + $appId = '1'; + $secret = '123456'; + + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $projectId . '/oauth2', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'provider' => $provider, + 'appId' => $appId, + 'secret' => $secret, + 'enabled' => true, + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + /** Test oauth2 and get invalid `success` URL */ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], [ + 'success' => 'https://example.com', + 'failure' => 'https://example.com' + ]); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertStringContainsString('Invalid `success` param: URL host must be one of: localhost, appwrite.io, *.appwrite.io', $response['body']); + + /** Test oauth2 with devKey and now get oauth2 is disabled */ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'] + ], [ + 'success' => 'https://example.com', + 'failure' => 'https://example.com' + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + /** Test hostname in Magic URL */ + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], [ + 'userId' => ID::unique(), + 'email' => 'user@appwrite.io', + 'url' => 'https://example.com', + ]); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('Invalid `url` param: URL host must be one of: localhost, appwrite.io, *.appwrite.io', $response['body']['message']); + + /** Test hostname in Magic URL with devKey */ + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'] + ], [ + 'userId' => ID::unique(), + 'email' => 'user@appwrite.io', + 'url' => 'https://example.com', + ]); + $this->assertEquals(201, $response['headers']['status-code']); + } + + /** + * @group devKeys + */ + public function testCorsWithDevKey(): void + { + /** + * Test for SUCCESS + */ + $projectId = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testCorsWithDevKey', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $devKey = $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + $origin = 'http://example.com'; + + /** + * Test CORS without Dev Key (should fail due to origin) + */ + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'origin' => $origin, + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + + $this->assertEquals(403, $response['headers']['status-code']); + $this->assertNotEquals($origin, $response['headers']['access-control-allow-origin'] ?? null); + $this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin'] ?? null); + + + /** + * Test CORS with Dev Key (should bypass origin check) + */ + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'origin' => $origin, + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'] + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + + $this->assertEquals(401, $response['headers']['status-code']); + $this->assertEquals('*', $response['headers']['access-control-allow-origin'] ?? null); + } + + /** + * @group devKeys + */ + public function testNoRateLimitWithDevKey(): void + { + /** + * Test for SUCCESS + */ + $projectId = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testNoRateLimitWithDevKey', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $devKey = $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + /** + * Test for SUCCESS + */ + for ($i = 0; $i < 10; $i++) { + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(401, $response['headers']['status-code']); + } + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(429, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'] + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(401, $response['headers']['status-code']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $projectId . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), -3600), + ]); + + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $response['body']['secret'] + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(429, $response['headers']['status-code']); + + /** + * Test for FAILURE after expire + */ + $devKey = $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test Expire 5 seconds', + 'expire' => DateTime::addSeconds(new \DateTime(), 5) + ]); + + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'] + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(401, $response['headers']['status-code']); + + sleep(5); + + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'] + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(429, $response['headers']['status-code']); + } + + /** + * @group devKeys + */ + public function testUpdateProjectDevKey(): void + { + $projectId = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testUpdateProjectDevKey', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $devKey = $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test Update', + 'expire' => DateTime::addSeconds(new \DateTime(), 360), + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals($devKey['$id'], $response['body']['$id']); + $this->assertEquals('Key Test Update', $response['body']['name']); + $this->assertArrayHasKey('accessedAt', $response['body']); + $this->assertEmpty($response['body']['accessedAt']); + + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals($devKey['$id'], $response['body']['$id']); + $this->assertEquals('Key Test Update', $response['body']['name']); + $this->assertArrayHasKey('accessedAt', $response['body']); + $this->assertEmpty($response['body']['accessedAt']); + } + + /** + * @group devKeys + */ + public function testDeleteProjectDevKey(): void + { + $projectId = $this->setupProject([ + 'projectId' => ID::unique(), + 'name' => 'testDeleteProjectDevKey', + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $devKey = $this->setupDevKey([ + 'projectId' => $projectId, + 'name' => 'Dev Key Test', + 'expire' => DateTime::addSeconds(new \DateTime(), 36000) + ]); + + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEmpty($response['body']); + + /** + * Get rate limit trying to use the deleted key + */ + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-dev-key' => $devKey['secret'] + ], [ + 'email' => 'user@appwrite.io', + 'password' => 'password' + ]); + $this->assertEquals(429, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(404, $response['headers']['status-code']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId . '/dev-keys/error', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * Devkeys Tests ends here ------------------------------------------------ + */ } diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index d2d75409b8..2b2c884283 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -13,6 +13,9 @@ use Utopia\Database\Validator\Datetime as DatetimeValidator; trait StorageBase { + /** + * @group fileTokens + */ public function testCreateBucketFile(): array { /** diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 3fcd9c043d..1858fd50ad 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -337,18 +337,6 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'email' => $email, - 'name' => $name, - 'roles' => ['developer'], - 'url' => 'http://example.com/join-us#title' // bad url - ]); - - $this->assertEquals(400, $response['headers']['status-code']); - return [ 'teamUid' => $teamUid, 'teamName' => $teamName, diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index 4b5ade7cbf..dec61d5258 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -14,6 +14,30 @@ class TeamsConsoleClientTest extends Scope use ProjectConsole; use SideClient; + /** + * @depends testCreateTeam + */ + public function testTeamCreateMembershipConsole($data): array + { + $teamUid = $data['teamUid'] ?? ''; + $email = uniqid() . 'friend@localhost.test'; + $name = 'Friend User'; + + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'email' => $email, + 'name' => $name, + 'roles' => ['developer'], + 'url' => 'http://example.com/join-us#title' // bad url + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + return $data; + } + /** * @depends testCreateTeam */ diff --git a/tests/e2e/Services/Tokens/TokensBase.php b/tests/e2e/Services/Tokens/TokensBase.php new file mode 100644 index 0000000000..11f6897f15 --- /dev/null +++ b/tests/e2e/Services/Tokens/TokensBase.php @@ -0,0 +1,7 @@ +client->call(Client::METHOD_POST, '/storage/buckets', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'bucketId' => ID::unique(), + 'name' => 'Test Bucket', + 'fileSecurity' => true, + 'maximumFileSize' => 2000000, //2MB + 'allowedFileExtensions' => ['jpg', 'png', 'jfif'], + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + $this->assertEquals(201, $bucket['headers']['status-code']); + $this->assertNotEmpty($bucket['body']['$id']); + + $bucketId = $bucket['body']['$id']; + + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'fileId' => ID::unique(), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + $this->assertEquals(201, $file['headers']['status-code']); + $this->assertNotEmpty($file['body']['$id']); + + $fileId = $file['body']['$id']; + + $res = $this->client->call(Client::METHOD_POST, '/tokens/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders())); + + $this->assertEquals(201, $res['headers']['status-code']); + $this->assertEquals('files', $res['body']['resourceType']); + + $data = []; + $data['fileId'] = $fileId; + $data['bucketId'] = $bucketId; + $data['tokenId'] = $res['body']['$id']; + return $data; + } + + /** + * @depends testCreateToken + */ + public function testUpdateToken(array $data): array + { + $tokenId = $data['tokenId']; + + $expiry = DateTime::now(); + $res = $this->client->call(Client::METHOD_PATCH, '/tokens/' . $tokenId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'expire' => $expiry, + ]); + + $this->assertEquals($expiry, $res['body']['expire']); + return $data; + } + + /** + * @depends testUpdateToken + */ + public function testDeleteToken(array $data): array + { + $tokenId = $data['tokenId']; + + $res = $this->client->call(Client::METHOD_DELETE, '/tokens/' . $tokenId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $res['headers']['status-code']); + return $data; + } +}