Merge branch '1.8.x' of github.com:appwrite/appwrite into add-webhooks-and-functions-events

This commit is contained in:
shimon 2026-01-07 16:58:23 +02:00
commit 65bb8946f6
22 changed files with 1414 additions and 900 deletions

View file

@ -1103,7 +1103,6 @@ return [
'name' => Exception::RULE_VERIFICATION_FAILED,
'description' => 'Domain verification failed. Please check if your DNS records are correct and try again.',
'code' => 400,
'publish' => true
],
Exception::PROJECT_SMTP_CONFIG_INVALID => [
'name' => Exception::PROJECT_SMTP_CONFIG_INVALID,

View file

@ -1,7 +1,7 @@
{
"openapi": "3.0.0",
"info": {
"version": "1.8.0",
"version": "1.8.1",
"title": "Appwrite",
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
@ -7318,7 +7318,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 454,
"weight": 455,
"cookies": false,
"type": "",
"demo": "functions\/list-executions.md",
@ -7405,7 +7405,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 452,
"weight": 453,
"cookies": false,
"type": "",
"demo": "functions\/create-execution.md",
@ -7523,7 +7523,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 453,
"weight": 454,
"cookies": false,
"type": "",
"demo": "functions\/get-execution.md",
@ -8298,7 +8298,7 @@
"x-appwrite": {
"method": "listFiles",
"group": "files",
"weight": 525,
"weight": 526,
"cookies": false,
"type": "",
"demo": "storage\/list-files.md",
@ -8397,7 +8397,7 @@
"x-appwrite": {
"method": "createFile",
"group": "files",
"weight": 523,
"weight": 524,
"cookies": false,
"type": "upload",
"demo": "storage\/create-file.md",
@ -8498,7 +8498,7 @@
"x-appwrite": {
"method": "getFile",
"group": "files",
"weight": 524,
"weight": 525,
"cookies": false,
"type": "",
"demo": "storage\/get-file.md",
@ -8572,7 +8572,7 @@
"x-appwrite": {
"method": "updateFile",
"group": "files",
"weight": 526,
"weight": 527,
"cookies": false,
"type": "",
"demo": "storage\/update-file.md",
@ -8664,7 +8664,7 @@
"x-appwrite": {
"method": "deleteFile",
"group": "files",
"weight": 527,
"weight": 528,
"cookies": false,
"type": "",
"demo": "storage\/delete-file.md",
@ -8733,7 +8733,7 @@
"x-appwrite": {
"method": "getFileDownload",
"group": "files",
"weight": 529,
"weight": 530,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-download.md",
@ -8813,7 +8813,7 @@
"x-appwrite": {
"method": "getFilePreview",
"group": "files",
"weight": 528,
"weight": 529,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-preview.md",
@ -9043,7 +9043,7 @@
"x-appwrite": {
"method": "getFileView",
"group": "files",
"weight": 530,
"weight": 531,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-view.md",

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{
"openapi": "3.0.0",
"info": {
"version": "1.8.0",
"version": "1.8.1",
"title": "Appwrite",
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
@ -12355,7 +12355,7 @@
"x-appwrite": {
"method": "list",
"group": "functions",
"weight": 438,
"weight": 439,
"cookies": false,
"type": "",
"demo": "functions\/list.md",
@ -12441,7 +12441,7 @@
"x-appwrite": {
"method": "create",
"group": "functions",
"weight": 435,
"weight": 436,
"cookies": false,
"type": "",
"demo": "functions\/create.md",
@ -12737,7 +12737,7 @@
"x-appwrite": {
"method": "listRuntimes",
"group": "runtimes",
"weight": 440,
"weight": 441,
"cookies": false,
"type": "",
"demo": "functions\/list-runtimes.md",
@ -12788,7 +12788,7 @@
"x-appwrite": {
"method": "listSpecifications",
"group": "runtimes",
"weight": 441,
"weight": 442,
"cookies": false,
"type": "",
"demo": "functions\/list-specifications.md",
@ -12839,7 +12839,7 @@
"x-appwrite": {
"method": "get",
"group": "functions",
"weight": 436,
"weight": 437,
"cookies": false,
"type": "",
"demo": "functions\/get.md",
@ -12900,7 +12900,7 @@
"x-appwrite": {
"method": "update",
"group": "functions",
"weight": 437,
"weight": 438,
"cookies": false,
"type": "",
"demo": "functions\/update.md",
@ -13193,7 +13193,7 @@
"x-appwrite": {
"method": "delete",
"group": "functions",
"weight": 439,
"weight": 440,
"cookies": false,
"type": "",
"demo": "functions\/delete.md",
@ -13256,7 +13256,7 @@
"x-appwrite": {
"method": "updateFunctionDeployment",
"group": "functions",
"weight": 444,
"weight": 445,
"cookies": false,
"type": "",
"demo": "functions\/update-function-deployment.md",
@ -13338,7 +13338,7 @@
"x-appwrite": {
"method": "listDeployments",
"group": "deployments",
"weight": 445,
"weight": 446,
"cookies": false,
"type": "",
"demo": "functions\/list-deployments.md",
@ -13434,7 +13434,7 @@
"x-appwrite": {
"method": "createDeployment",
"group": "deployments",
"weight": 442,
"weight": 443,
"cookies": false,
"type": "upload",
"demo": "functions\/create-deployment.md",
@ -13534,7 +13534,7 @@
"x-appwrite": {
"method": "createDuplicateDeployment",
"group": "deployments",
"weight": 450,
"weight": 451,
"cookies": false,
"type": "",
"demo": "functions\/create-duplicate-deployment.md",
@ -13621,7 +13621,7 @@
"x-appwrite": {
"method": "createTemplateDeployment",
"group": "deployments",
"weight": 447,
"weight": 448,
"cookies": false,
"type": "",
"demo": "functions\/create-template-deployment.md",
@ -13739,7 +13739,7 @@
"x-appwrite": {
"method": "createVcsDeployment",
"group": "deployments",
"weight": 448,
"weight": 449,
"cookies": false,
"type": "",
"demo": "functions\/create-vcs-deployment.md",
@ -13838,7 +13838,7 @@
"x-appwrite": {
"method": "getDeployment",
"group": "deployments",
"weight": 443,
"weight": 444,
"cookies": false,
"type": "",
"demo": "functions\/get-deployment.md",
@ -13902,7 +13902,7 @@
"x-appwrite": {
"method": "deleteDeployment",
"group": "deployments",
"weight": 446,
"weight": 447,
"cookies": false,
"type": "",
"demo": "functions\/delete-deployment.md",
@ -13968,7 +13968,7 @@
"x-appwrite": {
"method": "getDeploymentDownload",
"group": "deployments",
"weight": 449,
"weight": 450,
"cookies": false,
"type": "location",
"demo": "functions\/get-deployment-download.md",
@ -14060,7 +14060,7 @@
"x-appwrite": {
"method": "updateDeploymentStatus",
"group": "deployments",
"weight": 451,
"weight": 452,
"cookies": false,
"type": "",
"demo": "functions\/update-deployment-status.md",
@ -14133,7 +14133,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 454,
"weight": 455,
"cookies": false,
"type": "",
"demo": "functions\/list-executions.md",
@ -14222,7 +14222,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 452,
"weight": 453,
"cookies": false,
"type": "",
"demo": "functions\/create-execution.md",
@ -14342,7 +14342,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 453,
"weight": 454,
"cookies": false,
"type": "",
"demo": "functions\/get-execution.md",
@ -14410,7 +14410,7 @@
"x-appwrite": {
"method": "deleteExecution",
"group": "executions",
"weight": 455,
"weight": 456,
"cookies": false,
"type": "",
"demo": "functions\/delete-execution.md",
@ -14483,7 +14483,7 @@
"x-appwrite": {
"method": "listVariables",
"group": "variables",
"weight": 460,
"weight": 461,
"cookies": false,
"type": "",
"demo": "functions\/list-variables.md",
@ -14544,7 +14544,7 @@
"x-appwrite": {
"method": "createVariable",
"group": "variables",
"weight": 458,
"weight": 459,
"cookies": false,
"type": "",
"demo": "functions\/create-variable.md",
@ -14637,7 +14637,7 @@
"x-appwrite": {
"method": "getVariable",
"group": "variables",
"weight": 459,
"weight": 460,
"cookies": false,
"type": "",
"demo": "functions\/get-variable.md",
@ -14708,7 +14708,7 @@
"x-appwrite": {
"method": "updateVariable",
"group": "variables",
"weight": 461,
"weight": 462,
"cookies": false,
"type": "",
"demo": "functions\/update-variable.md",
@ -14803,7 +14803,7 @@
"x-appwrite": {
"method": "deleteVariable",
"group": "variables",
"weight": 462,
"weight": 463,
"cookies": false,
"type": "",
"demo": "functions\/delete-variable.md",
@ -22240,7 +22240,7 @@
"x-appwrite": {
"method": "list",
"group": "sites",
"weight": 467,
"weight": 468,
"cookies": false,
"type": "",
"demo": "sites\/list.md",
@ -22326,7 +22326,7 @@
"x-appwrite": {
"method": "create",
"group": "sites",
"weight": 465,
"weight": 466,
"cookies": false,
"type": "",
"demo": "sites\/create.md",
@ -22580,7 +22580,7 @@
"x-appwrite": {
"method": "listFrameworks",
"group": "frameworks",
"weight": 470,
"weight": 471,
"cookies": false,
"type": "",
"demo": "sites\/list-frameworks.md",
@ -22631,7 +22631,7 @@
"x-appwrite": {
"method": "listSpecifications",
"group": "frameworks",
"weight": 493,
"weight": 494,
"cookies": false,
"type": "",
"demo": "sites\/list-specifications.md",
@ -22682,7 +22682,7 @@
"x-appwrite": {
"method": "get",
"group": "sites",
"weight": 466,
"weight": 467,
"cookies": false,
"type": "",
"demo": "sites\/get.md",
@ -22743,7 +22743,7 @@
"x-appwrite": {
"method": "update",
"group": "sites",
"weight": 468,
"weight": 469,
"cookies": false,
"type": "",
"demo": "sites\/update.md",
@ -22993,7 +22993,7 @@
"x-appwrite": {
"method": "delete",
"group": "sites",
"weight": 469,
"weight": 470,
"cookies": false,
"type": "",
"demo": "sites\/delete.md",
@ -23056,7 +23056,7 @@
"x-appwrite": {
"method": "updateSiteDeployment",
"group": "sites",
"weight": 476,
"weight": 477,
"cookies": false,
"type": "",
"demo": "sites\/update-site-deployment.md",
@ -23138,7 +23138,7 @@
"x-appwrite": {
"method": "listDeployments",
"group": "deployments",
"weight": 475,
"weight": 476,
"cookies": false,
"type": "",
"demo": "sites\/list-deployments.md",
@ -23234,7 +23234,7 @@
"x-appwrite": {
"method": "createDeployment",
"group": "deployments",
"weight": 471,
"weight": 472,
"cookies": false,
"type": "upload",
"demo": "sites\/create-deployment.md",
@ -23340,7 +23340,7 @@
"x-appwrite": {
"method": "createDuplicateDeployment",
"group": "deployments",
"weight": 479,
"weight": 480,
"cookies": false,
"type": "",
"demo": "sites\/create-duplicate-deployment.md",
@ -23422,7 +23422,7 @@
"x-appwrite": {
"method": "createTemplateDeployment",
"group": "deployments",
"weight": 472,
"weight": 473,
"cookies": false,
"type": "",
"demo": "sites\/create-template-deployment.md",
@ -23540,7 +23540,7 @@
"x-appwrite": {
"method": "createVcsDeployment",
"group": "deployments",
"weight": 473,
"weight": 474,
"cookies": false,
"type": "",
"demo": "sites\/create-vcs-deployment.md",
@ -23640,7 +23640,7 @@
"x-appwrite": {
"method": "getDeployment",
"group": "deployments",
"weight": 474,
"weight": 475,
"cookies": false,
"type": "",
"demo": "sites\/get-deployment.md",
@ -23704,7 +23704,7 @@
"x-appwrite": {
"method": "deleteDeployment",
"group": "deployments",
"weight": 477,
"weight": 478,
"cookies": false,
"type": "",
"demo": "sites\/delete-deployment.md",
@ -23770,7 +23770,7 @@
"x-appwrite": {
"method": "getDeploymentDownload",
"group": "deployments",
"weight": 478,
"weight": 479,
"cookies": false,
"type": "location",
"demo": "sites\/get-deployment-download.md",
@ -23862,7 +23862,7 @@
"x-appwrite": {
"method": "updateDeploymentStatus",
"group": "deployments",
"weight": 480,
"weight": 481,
"cookies": false,
"type": "",
"demo": "sites\/update-deployment-status.md",
@ -23935,7 +23935,7 @@
"x-appwrite": {
"method": "listLogs",
"group": "logs",
"weight": 482,
"weight": 483,
"cookies": false,
"type": "",
"demo": "sites\/list-logs.md",
@ -24022,7 +24022,7 @@
"x-appwrite": {
"method": "getLog",
"group": "logs",
"weight": 481,
"weight": 482,
"cookies": false,
"type": "",
"demo": "sites\/get-log.md",
@ -24086,7 +24086,7 @@
"x-appwrite": {
"method": "deleteLog",
"group": "logs",
"weight": 483,
"weight": 484,
"cookies": false,
"type": "",
"demo": "sites\/delete-log.md",
@ -24159,7 +24159,7 @@
"x-appwrite": {
"method": "listVariables",
"group": "variables",
"weight": 486,
"weight": 487,
"cookies": false,
"type": "",
"demo": "sites\/list-variables.md",
@ -24220,7 +24220,7 @@
"x-appwrite": {
"method": "createVariable",
"group": "variables",
"weight": 484,
"weight": 485,
"cookies": false,
"type": "",
"demo": "sites\/create-variable.md",
@ -24313,7 +24313,7 @@
"x-appwrite": {
"method": "getVariable",
"group": "variables",
"weight": 485,
"weight": 486,
"cookies": false,
"type": "",
"demo": "sites\/get-variable.md",
@ -24384,7 +24384,7 @@
"x-appwrite": {
"method": "updateVariable",
"group": "variables",
"weight": 487,
"weight": 488,
"cookies": false,
"type": "",
"demo": "sites\/update-variable.md",
@ -24479,7 +24479,7 @@
"x-appwrite": {
"method": "deleteVariable",
"group": "variables",
"weight": 488,
"weight": 489,
"cookies": false,
"type": "",
"demo": "sites\/delete-variable.md",
@ -24552,7 +24552,7 @@
"x-appwrite": {
"method": "listBuckets",
"group": "buckets",
"weight": 520,
"weight": 521,
"cookies": false,
"type": "",
"demo": "storage\/list-buckets.md",
@ -24639,7 +24639,7 @@
"x-appwrite": {
"method": "createBucket",
"group": "buckets",
"weight": 518,
"weight": 519,
"cookies": false,
"type": "",
"demo": "storage\/create-bucket.md",
@ -24715,7 +24715,7 @@
},
"compression": {
"type": "string",
"description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled",
"description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled",
"x-example": "none",
"enum": [
"none",
@ -24775,7 +24775,7 @@
"x-appwrite": {
"method": "getBucket",
"group": "buckets",
"weight": 519,
"weight": 520,
"cookies": false,
"type": "",
"demo": "storage\/get-bucket.md",
@ -24837,7 +24837,7 @@
"x-appwrite": {
"method": "updateBucket",
"group": "buckets",
"weight": 521,
"weight": 522,
"cookies": false,
"type": "",
"demo": "storage\/update-bucket.md",
@ -24920,7 +24920,7 @@
},
"compression": {
"type": "string",
"description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled",
"description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled",
"x-example": "none",
"enum": [
"none",
@ -24970,7 +24970,7 @@
"x-appwrite": {
"method": "deleteBucket",
"group": "buckets",
"weight": 522,
"weight": 523,
"cookies": false,
"type": "",
"demo": "storage\/delete-bucket.md",
@ -25034,7 +25034,7 @@
"x-appwrite": {
"method": "listFiles",
"group": "files",
"weight": 525,
"weight": 526,
"cookies": false,
"type": "",
"demo": "storage\/list-files.md",
@ -25135,7 +25135,7 @@
"x-appwrite": {
"method": "createFile",
"group": "files",
"weight": 523,
"weight": 524,
"cookies": false,
"type": "upload",
"demo": "storage\/create-file.md",
@ -25238,7 +25238,7 @@
"x-appwrite": {
"method": "getFile",
"group": "files",
"weight": 524,
"weight": 525,
"cookies": false,
"type": "",
"demo": "storage\/get-file.md",
@ -25314,7 +25314,7 @@
"x-appwrite": {
"method": "updateFile",
"group": "files",
"weight": 526,
"weight": 527,
"cookies": false,
"type": "",
"demo": "storage\/update-file.md",
@ -25408,7 +25408,7 @@
"x-appwrite": {
"method": "deleteFile",
"group": "files",
"weight": 527,
"weight": 528,
"cookies": false,
"type": "",
"demo": "storage\/delete-file.md",
@ -25479,7 +25479,7 @@
"x-appwrite": {
"method": "getFileDownload",
"group": "files",
"weight": 529,
"weight": 530,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-download.md",
@ -25561,7 +25561,7 @@
"x-appwrite": {
"method": "getFilePreview",
"group": "files",
"weight": 528,
"weight": 529,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-preview.md",
@ -25793,7 +25793,7 @@
"x-appwrite": {
"method": "getFileView",
"group": "files",
"weight": 530,
"weight": 531,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-view.md",
@ -33532,7 +33532,7 @@
"x-appwrite": {
"method": "list",
"group": "files",
"weight": 515,
"weight": 516,
"cookies": false,
"type": "",
"demo": "tokens\/list.md",
@ -33627,7 +33627,7 @@
"x-appwrite": {
"method": "createFileToken",
"group": "files",
"weight": 513,
"weight": 514,
"cookies": false,
"type": "",
"demo": "tokens\/create-file-token.md",
@ -33717,7 +33717,7 @@
"x-appwrite": {
"method": "get",
"group": "tokens",
"weight": 514,
"weight": 515,
"cookies": false,
"type": "",
"demo": "tokens\/get.md",
@ -33778,7 +33778,7 @@
"x-appwrite": {
"method": "update",
"group": "tokens",
"weight": 516,
"weight": 517,
"cookies": false,
"type": "",
"demo": "tokens\/update.md",
@ -33849,7 +33849,7 @@
"x-appwrite": {
"method": "delete",
"group": "tokens",
"weight": 517,
"weight": 518,
"cookies": false,
"type": "",
"demo": "tokens\/delete.md",
@ -43220,7 +43220,7 @@
},
"compression": {
"type": "string",
"description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).",
"description": "Compression algorithm chosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).",
"x-example": "gzip"
},
"encryption": {
@ -43237,6 +43237,12 @@
"type": "boolean",
"description": "Image transformations are enabled.",
"x-example": false
},
"totalSize": {
"type": "integer",
"description": "Total size of this bucket in bytes.",
"x-example": 128,
"format": "int32"
}
},
"required": [
@ -43252,7 +43258,8 @@
"compression",
"encryption",
"antivirus",
"transformations"
"transformations",
"totalSize"
],
"example": {
"$id": "5e5ea5c16897e",
@ -43272,7 +43279,8 @@
"compression": "gzip",
"encryption": false,
"antivirus": false,
"transformations": false
"transformations": false,
"totalSize": 128
}
},
"resourceToken": {

View file

@ -1,7 +1,7 @@
{
"swagger": "2.0",
"info": {
"version": "1.8.0",
"version": "1.8.1",
"title": "Appwrite",
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
@ -7375,7 +7375,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 454,
"weight": 455,
"cookies": false,
"type": "",
"demo": "functions\/list-executions.md",
@ -7458,7 +7458,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 452,
"weight": 453,
"cookies": false,
"type": "",
"demo": "functions\/create-execution.md",
@ -7577,7 +7577,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 453,
"weight": 454,
"cookies": false,
"type": "",
"demo": "functions\/get-execution.md",
@ -8379,7 +8379,7 @@
"x-appwrite": {
"method": "listFiles",
"group": "files",
"weight": 525,
"weight": 526,
"cookies": false,
"type": "",
"demo": "storage\/list-files.md",
@ -8472,7 +8472,7 @@
"x-appwrite": {
"method": "createFile",
"group": "files",
"weight": 523,
"weight": 524,
"cookies": false,
"type": "upload",
"demo": "storage\/create-file.md",
@ -8563,7 +8563,7 @@
"x-appwrite": {
"method": "getFile",
"group": "files",
"weight": 524,
"weight": 525,
"cookies": false,
"type": "",
"demo": "storage\/get-file.md",
@ -8634,7 +8634,7 @@
"x-appwrite": {
"method": "updateFile",
"group": "files",
"weight": 526,
"weight": 527,
"cookies": false,
"type": "",
"demo": "storage\/update-file.md",
@ -8725,7 +8725,7 @@
"x-appwrite": {
"method": "deleteFile",
"group": "files",
"weight": 527,
"weight": 528,
"cookies": false,
"type": "",
"demo": "storage\/delete-file.md",
@ -8796,7 +8796,7 @@
"x-appwrite": {
"method": "getFileDownload",
"group": "files",
"weight": 529,
"weight": 530,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-download.md",
@ -8876,7 +8876,7 @@
"x-appwrite": {
"method": "getFilePreview",
"group": "files",
"weight": 528,
"weight": 529,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-preview.md",
@ -9084,7 +9084,7 @@
"x-appwrite": {
"method": "getFileView",
"group": "files",
"weight": 530,
"weight": 531,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-view.md",

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{
"swagger": "2.0",
"info": {
"version": "1.8.0",
"version": "1.8.1",
"title": "Appwrite",
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
@ -12308,7 +12308,7 @@
"x-appwrite": {
"method": "list",
"group": "functions",
"weight": 438,
"weight": 439,
"cookies": false,
"type": "",
"demo": "functions\/list.md",
@ -12391,7 +12391,7 @@
"x-appwrite": {
"method": "create",
"group": "functions",
"weight": 435,
"weight": 436,
"cookies": false,
"type": "",
"demo": "functions\/create.md",
@ -12705,7 +12705,7 @@
"x-appwrite": {
"method": "listRuntimes",
"group": "runtimes",
"weight": 440,
"weight": 441,
"cookies": false,
"type": "",
"demo": "functions\/list-runtimes.md",
@ -12756,7 +12756,7 @@
"x-appwrite": {
"method": "listSpecifications",
"group": "runtimes",
"weight": 441,
"weight": 442,
"cookies": false,
"type": "",
"demo": "functions\/list-specifications.md",
@ -12807,7 +12807,7 @@
"x-appwrite": {
"method": "get",
"group": "functions",
"weight": 436,
"weight": 437,
"cookies": false,
"type": "",
"demo": "functions\/get.md",
@ -12868,7 +12868,7 @@
"x-appwrite": {
"method": "update",
"group": "functions",
"weight": 437,
"weight": 438,
"cookies": false,
"type": "",
"demo": "functions\/update.md",
@ -13178,7 +13178,7 @@
"x-appwrite": {
"method": "delete",
"group": "functions",
"weight": 439,
"weight": 440,
"cookies": false,
"type": "",
"demo": "functions\/delete.md",
@ -13241,7 +13241,7 @@
"x-appwrite": {
"method": "updateFunctionDeployment",
"group": "functions",
"weight": 444,
"weight": 445,
"cookies": false,
"type": "",
"demo": "functions\/update-function-deployment.md",
@ -13320,7 +13320,7 @@
"x-appwrite": {
"method": "listDeployments",
"group": "deployments",
"weight": 445,
"weight": 446,
"cookies": false,
"type": "",
"demo": "functions\/list-deployments.md",
@ -13411,7 +13411,7 @@
"x-appwrite": {
"method": "createDeployment",
"group": "deployments",
"weight": 442,
"weight": 443,
"cookies": false,
"type": "upload",
"demo": "functions\/create-deployment.md",
@ -13505,7 +13505,7 @@
"x-appwrite": {
"method": "createDuplicateDeployment",
"group": "deployments",
"weight": 450,
"weight": 451,
"cookies": false,
"type": "",
"demo": "functions\/create-duplicate-deployment.md",
@ -13592,7 +13592,7 @@
"x-appwrite": {
"method": "createTemplateDeployment",
"group": "deployments",
"weight": 447,
"weight": 448,
"cookies": false,
"type": "",
"demo": "functions\/create-template-deployment.md",
@ -13714,7 +13714,7 @@
"x-appwrite": {
"method": "createVcsDeployment",
"group": "deployments",
"weight": 448,
"weight": 449,
"cookies": false,
"type": "",
"demo": "functions\/create-vcs-deployment.md",
@ -13812,7 +13812,7 @@
"x-appwrite": {
"method": "getDeployment",
"group": "deployments",
"weight": 443,
"weight": 444,
"cookies": false,
"type": "",
"demo": "functions\/get-deployment.md",
@ -13876,7 +13876,7 @@
"x-appwrite": {
"method": "deleteDeployment",
"group": "deployments",
"weight": 446,
"weight": 447,
"cookies": false,
"type": "",
"demo": "functions\/delete-deployment.md",
@ -13945,7 +13945,7 @@
"x-appwrite": {
"method": "getDeploymentDownload",
"group": "deployments",
"weight": 449,
"weight": 450,
"cookies": false,
"type": "location",
"demo": "functions\/get-deployment-download.md",
@ -14032,7 +14032,7 @@
"x-appwrite": {
"method": "updateDeploymentStatus",
"group": "deployments",
"weight": 451,
"weight": 452,
"cookies": false,
"type": "",
"demo": "functions\/update-deployment-status.md",
@ -14101,7 +14101,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 454,
"weight": 455,
"cookies": false,
"type": "",
"demo": "functions\/list-executions.md",
@ -14186,7 +14186,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 452,
"weight": 453,
"cookies": false,
"type": "",
"demo": "functions\/create-execution.md",
@ -14307,7 +14307,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 453,
"weight": 454,
"cookies": false,
"type": "",
"demo": "functions\/get-execution.md",
@ -14374,7 +14374,7 @@
"x-appwrite": {
"method": "deleteExecution",
"group": "executions",
"weight": 455,
"weight": 456,
"cookies": false,
"type": "",
"demo": "functions\/delete-execution.md",
@ -14443,7 +14443,7 @@
"x-appwrite": {
"method": "listVariables",
"group": "variables",
"weight": 460,
"weight": 461,
"cookies": false,
"type": "",
"demo": "functions\/list-variables.md",
@ -14504,7 +14504,7 @@
"x-appwrite": {
"method": "createVariable",
"group": "variables",
"weight": 458,
"weight": 459,
"cookies": false,
"type": "",
"demo": "functions\/create-variable.md",
@ -14596,7 +14596,7 @@
"x-appwrite": {
"method": "getVariable",
"group": "variables",
"weight": 459,
"weight": 460,
"cookies": false,
"type": "",
"demo": "functions\/get-variable.md",
@ -14665,7 +14665,7 @@
"x-appwrite": {
"method": "updateVariable",
"group": "variables",
"weight": 461,
"weight": 462,
"cookies": false,
"type": "",
"demo": "functions\/update-variable.md",
@ -14761,7 +14761,7 @@
"x-appwrite": {
"method": "deleteVariable",
"group": "variables",
"weight": 462,
"weight": 463,
"cookies": false,
"type": "",
"demo": "functions\/delete-variable.md",
@ -22376,7 +22376,7 @@
"x-appwrite": {
"method": "list",
"group": "sites",
"weight": 467,
"weight": 468,
"cookies": false,
"type": "",
"demo": "sites\/list.md",
@ -22459,7 +22459,7 @@
"x-appwrite": {
"method": "create",
"group": "sites",
"weight": 465,
"weight": 466,
"cookies": false,
"type": "",
"demo": "sites\/create.md",
@ -22731,7 +22731,7 @@
"x-appwrite": {
"method": "listFrameworks",
"group": "frameworks",
"weight": 470,
"weight": 471,
"cookies": false,
"type": "",
"demo": "sites\/list-frameworks.md",
@ -22782,7 +22782,7 @@
"x-appwrite": {
"method": "listSpecifications",
"group": "frameworks",
"weight": 493,
"weight": 494,
"cookies": false,
"type": "",
"demo": "sites\/list-specifications.md",
@ -22833,7 +22833,7 @@
"x-appwrite": {
"method": "get",
"group": "sites",
"weight": 466,
"weight": 467,
"cookies": false,
"type": "",
"demo": "sites\/get.md",
@ -22894,7 +22894,7 @@
"x-appwrite": {
"method": "update",
"group": "sites",
"weight": 468,
"weight": 469,
"cookies": false,
"type": "",
"demo": "sites\/update.md",
@ -23161,7 +23161,7 @@
"x-appwrite": {
"method": "delete",
"group": "sites",
"weight": 469,
"weight": 470,
"cookies": false,
"type": "",
"demo": "sites\/delete.md",
@ -23224,7 +23224,7 @@
"x-appwrite": {
"method": "updateSiteDeployment",
"group": "sites",
"weight": 476,
"weight": 477,
"cookies": false,
"type": "",
"demo": "sites\/update-site-deployment.md",
@ -23303,7 +23303,7 @@
"x-appwrite": {
"method": "listDeployments",
"group": "deployments",
"weight": 475,
"weight": 476,
"cookies": false,
"type": "",
"demo": "sites\/list-deployments.md",
@ -23394,7 +23394,7 @@
"x-appwrite": {
"method": "createDeployment",
"group": "deployments",
"weight": 471,
"weight": 472,
"cookies": false,
"type": "upload",
"demo": "sites\/create-deployment.md",
@ -23496,7 +23496,7 @@
"x-appwrite": {
"method": "createDuplicateDeployment",
"group": "deployments",
"weight": 479,
"weight": 480,
"cookies": false,
"type": "",
"demo": "sites\/create-duplicate-deployment.md",
@ -23577,7 +23577,7 @@
"x-appwrite": {
"method": "createTemplateDeployment",
"group": "deployments",
"weight": 472,
"weight": 473,
"cookies": false,
"type": "",
"demo": "sites\/create-template-deployment.md",
@ -23699,7 +23699,7 @@
"x-appwrite": {
"method": "createVcsDeployment",
"group": "deployments",
"weight": 473,
"weight": 474,
"cookies": false,
"type": "",
"demo": "sites\/create-vcs-deployment.md",
@ -23798,7 +23798,7 @@
"x-appwrite": {
"method": "getDeployment",
"group": "deployments",
"weight": 474,
"weight": 475,
"cookies": false,
"type": "",
"demo": "sites\/get-deployment.md",
@ -23862,7 +23862,7 @@
"x-appwrite": {
"method": "deleteDeployment",
"group": "deployments",
"weight": 477,
"weight": 478,
"cookies": false,
"type": "",
"demo": "sites\/delete-deployment.md",
@ -23931,7 +23931,7 @@
"x-appwrite": {
"method": "getDeploymentDownload",
"group": "deployments",
"weight": 478,
"weight": 479,
"cookies": false,
"type": "location",
"demo": "sites\/get-deployment-download.md",
@ -24018,7 +24018,7 @@
"x-appwrite": {
"method": "updateDeploymentStatus",
"group": "deployments",
"weight": 480,
"weight": 481,
"cookies": false,
"type": "",
"demo": "sites\/update-deployment-status.md",
@ -24087,7 +24087,7 @@
"x-appwrite": {
"method": "listLogs",
"group": "logs",
"weight": 482,
"weight": 483,
"cookies": false,
"type": "",
"demo": "sites\/list-logs.md",
@ -24169,7 +24169,7 @@
"x-appwrite": {
"method": "getLog",
"group": "logs",
"weight": 481,
"weight": 482,
"cookies": false,
"type": "",
"demo": "sites\/get-log.md",
@ -24235,7 +24235,7 @@
"x-appwrite": {
"method": "deleteLog",
"group": "logs",
"weight": 483,
"weight": 484,
"cookies": false,
"type": "",
"demo": "sites\/delete-log.md",
@ -24304,7 +24304,7 @@
"x-appwrite": {
"method": "listVariables",
"group": "variables",
"weight": 486,
"weight": 487,
"cookies": false,
"type": "",
"demo": "sites\/list-variables.md",
@ -24365,7 +24365,7 @@
"x-appwrite": {
"method": "createVariable",
"group": "variables",
"weight": 484,
"weight": 485,
"cookies": false,
"type": "",
"demo": "sites\/create-variable.md",
@ -24457,7 +24457,7 @@
"x-appwrite": {
"method": "getVariable",
"group": "variables",
"weight": 485,
"weight": 486,
"cookies": false,
"type": "",
"demo": "sites\/get-variable.md",
@ -24526,7 +24526,7 @@
"x-appwrite": {
"method": "updateVariable",
"group": "variables",
"weight": 487,
"weight": 488,
"cookies": false,
"type": "",
"demo": "sites\/update-variable.md",
@ -24622,7 +24622,7 @@
"x-appwrite": {
"method": "deleteVariable",
"group": "variables",
"weight": 488,
"weight": 489,
"cookies": false,
"type": "",
"demo": "sites\/delete-variable.md",
@ -24691,7 +24691,7 @@
"x-appwrite": {
"method": "listBuckets",
"group": "buckets",
"weight": 520,
"weight": 521,
"cookies": false,
"type": "",
"demo": "storage\/list-buckets.md",
@ -24775,7 +24775,7 @@
"x-appwrite": {
"method": "createBucket",
"group": "buckets",
"weight": 518,
"weight": 519,
"cookies": false,
"type": "",
"demo": "storage\/create-bucket.md",
@ -24859,7 +24859,7 @@
},
"compression": {
"type": "string",
"description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled",
"description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled",
"default": "none",
"x-example": "none",
"enum": [
@ -24922,7 +24922,7 @@
"x-appwrite": {
"method": "getBucket",
"group": "buckets",
"weight": 519,
"weight": 520,
"cookies": false,
"type": "",
"demo": "storage\/get-bucket.md",
@ -24984,7 +24984,7 @@
"x-appwrite": {
"method": "updateBucket",
"group": "buckets",
"weight": 521,
"weight": 522,
"cookies": false,
"type": "",
"demo": "storage\/update-bucket.md",
@ -25070,7 +25070,7 @@
},
"compression": {
"type": "string",
"description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled",
"description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled",
"default": "none",
"x-example": "none",
"enum": [
@ -25127,7 +25127,7 @@
"x-appwrite": {
"method": "deleteBucket",
"group": "buckets",
"weight": 522,
"weight": 523,
"cookies": false,
"type": "",
"demo": "storage\/delete-bucket.md",
@ -25189,7 +25189,7 @@
"x-appwrite": {
"method": "listFiles",
"group": "files",
"weight": 525,
"weight": 526,
"cookies": false,
"type": "",
"demo": "storage\/list-files.md",
@ -25284,7 +25284,7 @@
"x-appwrite": {
"method": "createFile",
"group": "files",
"weight": 523,
"weight": 524,
"cookies": false,
"type": "upload",
"demo": "storage\/create-file.md",
@ -25377,7 +25377,7 @@
"x-appwrite": {
"method": "getFile",
"group": "files",
"weight": 524,
"weight": 525,
"cookies": false,
"type": "",
"demo": "storage\/get-file.md",
@ -25450,7 +25450,7 @@
"x-appwrite": {
"method": "updateFile",
"group": "files",
"weight": 526,
"weight": 527,
"cookies": false,
"type": "",
"demo": "storage\/update-file.md",
@ -25543,7 +25543,7 @@
"x-appwrite": {
"method": "deleteFile",
"group": "files",
"weight": 527,
"weight": 528,
"cookies": false,
"type": "",
"demo": "storage\/delete-file.md",
@ -25616,7 +25616,7 @@
"x-appwrite": {
"method": "getFileDownload",
"group": "files",
"weight": 529,
"weight": 530,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-download.md",
@ -25698,7 +25698,7 @@
"x-appwrite": {
"method": "getFilePreview",
"group": "files",
"weight": 528,
"weight": 529,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-preview.md",
@ -25908,7 +25908,7 @@
"x-appwrite": {
"method": "getFileView",
"group": "files",
"weight": 530,
"weight": 531,
"cookies": false,
"type": "location",
"demo": "storage\/get-file-view.md",
@ -33457,7 +33457,7 @@
"x-appwrite": {
"method": "list",
"group": "files",
"weight": 515,
"weight": 516,
"cookies": false,
"type": "",
"demo": "tokens\/list.md",
@ -33547,7 +33547,7 @@
"x-appwrite": {
"method": "createFileToken",
"group": "files",
"weight": 513,
"weight": 514,
"cookies": false,
"type": "",
"demo": "tokens\/create-file-token.md",
@ -33632,7 +33632,7 @@
"x-appwrite": {
"method": "get",
"group": "tokens",
"weight": 514,
"weight": 515,
"cookies": false,
"type": "",
"demo": "tokens\/get.md",
@ -33693,7 +33693,7 @@
"x-appwrite": {
"method": "update",
"group": "tokens",
"weight": 516,
"weight": 517,
"cookies": false,
"type": "",
"demo": "tokens\/update.md",
@ -33765,7 +33765,7 @@
"x-appwrite": {
"method": "delete",
"group": "tokens",
"weight": 517,
"weight": 518,
"cookies": false,
"type": "",
"demo": "tokens\/delete.md",
@ -43148,7 +43148,7 @@
},
"compression": {
"type": "string",
"description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).",
"description": "Compression algorithm chosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).",
"x-example": "gzip"
},
"encryption": {
@ -43165,6 +43165,12 @@
"type": "boolean",
"description": "Image transformations are enabled.",
"x-example": false
},
"totalSize": {
"type": "integer",
"description": "Total size of this bucket in bytes.",
"x-example": 128,
"format": "int32"
}
},
"required": [
@ -43180,7 +43186,8 @@
"compression",
"encryption",
"antivirus",
"transformations"
"transformations",
"totalSize"
],
"example": {
"$id": "5e5ea5c16897e",
@ -43200,7 +43207,8 @@
"compression": "gzip",
"encryption": false,
"antivirus": false,
"transformations": false
"transformations": false,
"totalSize": 128
}
},
"resourceToken": {

View file

@ -1328,6 +1328,86 @@ App::error()
$log->addExtra('trace', $error->getTraceAsString());
$log->addExtra('roles', Authorization::getRoles());
try {
/* add queries to log */
$queries = $request->getParam('queries', []);
if (!empty($queries) && is_array($queries)) {
$parsedQueries = Query::parseQueries($queries);
// format query by removing sensitive values
$formatQuery = function (array $queryArray) use (&$formatQuery): ?array {
$method = $queryArray['method'] ?? '';
$values = $queryArray['values'] ?? [];
$attribute = $queryArray['attribute'] ?? '';
if (!is_string($method) || $method === '') {
return null;
}
// logical queries - recursively format nested queries
if (in_array($method, [Query::TYPE_AND, Query::TYPE_OR], true)) {
$nested = [];
foreach ($values as $nestedArray) {
if (is_array($nestedArray)) {
$formatted = $formatQuery($nestedArray);
if ($formatted !== null) {
$nested[] = $formatted;
}
}
}
return empty($nested) ? null : [$method => $nested];
}
// select - show selected attributes
if ($method === Query::TYPE_SELECT) {
$attributes = array_values(array_filter($values, 'is_string'));
return [$method => $attributes];
}
// pagination
if (in_array($method, [
Query::TYPE_LIMIT,
Query::TYPE_OFFSET,
Query::TYPE_CURSOR_AFTER,
Query::TYPE_CURSOR_BEFORE
], true)) {
return [$method => []];
}
// orders
if (in_array($method, [
Query::TYPE_ORDER_DESC,
Query::TYPE_ORDER_ASC,
Query::TYPE_ORDER_RANDOM
], true)) {
return [$method => !empty($attribute) ? [$attribute] : []];
}
// filter
if (!empty($attribute)) {
return [$method => [$attribute]];
}
// fallback
return [$method => []];
};
$formattedQueries = [];
foreach ($parsedQueries as $query) {
$formatted = $formatQuery($query->toArray());
if ($formatted !== null) {
$formattedQueries[] = $formatted;
}
}
if (!empty($formattedQueries)) {
$log->addExtra('queries', $formattedQueries);
}
}
} catch (Throwable $_) {
// don't fail the error handler
}
$action = 'UNKNOWN_NAMESPACE.UNKNOWN.METHOD';
if (!empty($sdk)) {
/** @var \Appwrite\SDK\Method $sdk */

View file

@ -64,7 +64,7 @@
"utopia-php/locale": "0.8.*",
"utopia-php/logger": "0.6.*",
"utopia-php/messaging": "0.20.*",
"utopia-php/migration": "1.*.*",
"utopia-php/migration": "1.3.*",
"utopia-php/orchestration": "0.9.*",
"utopia-php/platform": "0.7.*",
"utopia-php/pools": "0.8.*",
@ -100,6 +100,12 @@
"provide": {
"ext-phpiredis": "*"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/utopia-php/migration.git"
}
],
"config": {
"platform": {
"php": "8.3"

36
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9bac4d8946e35357efa46fd087c9484e",
"content-hash": "375a062e8675e7e6938c1d8cc7b61ecf",
"packages": [
{
"name": "adhocore/jwt",
@ -4516,16 +4516,16 @@
},
{
"name": "utopia-php/migration",
"version": "1.3.10",
"version": "1.3.12",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "cb357c42a5a5614605b546effbea1204ed64c6b0"
"reference": "1b8d5519c50630e4c0b6a79be615b70d5f23d2e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/cb357c42a5a5614605b546effbea1204ed64c6b0",
"reference": "cb357c42a5a5614605b546effbea1204ed64c6b0",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/1b8d5519c50630e4c0b6a79be615b70d5f23d2e4",
"reference": "1b8d5519c50630e4c0b6a79be615b70d5f23d2e4",
"shasum": ""
},
"require": {
@ -4551,7 +4551,25 @@
"Utopia\\Migration\\": "src/Migration"
}
},
"notification-url": "https://packagist.org/downloads/",
"autoload-dev": {
"psr-4": {
"Utopia\\Tests\\": "tests/Migration"
}
},
"scripts": {
"test": [
"./vendor/bin/phpunit"
],
"lint": [
"./vendor/bin/pint --test"
],
"format": [
"./vendor/bin/pint"
],
"check": [
"./vendor/bin/phpstan analyse --level 3 src tests --memory-limit 2G"
]
},
"license": [
"MIT"
],
@ -4564,10 +4582,10 @@
"utopia"
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/1.3.10"
"source": "https://github.com/utopia-php/migration/tree/1.3.12",
"issues": "https://github.com/utopia-php/migration/issues"
},
"time": "2026-01-06T10:47:11+00:00"
"time": "2026-01-07T06:07:33+00:00"
},
{
"name": "utopia-php/mongo",

View file

@ -68,7 +68,7 @@ class Create extends Action
->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true)
->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan'])
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm chosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
->param('transformations', true, new Boolean(true), 'Are image transformations enabled?', true)

View file

@ -8,6 +8,9 @@ use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\UID;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@ -46,20 +49,48 @@ class Get extends Action
->param('bucketId', '', new UID(), 'Bucket unique ID.')
->inject('response')
->inject('dbForProject')
->inject('project')
->inject('getLogsDB')
->callback($this->action(...));
}
public function action(
string $bucketId,
Response $response,
Database $dbForProject
) {
Database $dbForProject,
Document $project,
callable $getLogsDB
): void {
$bucket = $dbForProject->getDocument('buckets', $bucketId);
if ($bucket->isEmpty()) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$metric = str_replace(
'{bucketInternalId}',
$bucket->getSequence(),
METRIC_BUCKET_ID_FILES_STORAGE
);
$statsDocId = md5('_inf_' . $metric);
$dbForLogs = call_user_func($getLogsDB, $project);
$storageStats = Authorization::skip(
fn () => $dbForLogs->getDocument(
'stats',
$statsDocId,
[Query::select(['value'])]
)
);
/**
* The value can be 0 if stats were not aggregated when this request was made!
*/
$totalSize = $storageStats->isEmpty() ? 0 : $storageStats->getAttribute('value', 0);
$bucket->setAttribute('totalSize', $totalSize);
$response->dynamic($bucket, Response::MODEL_BUCKET);
}
}

View file

@ -65,7 +65,7 @@ class Update extends Action
->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true)
->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan'])
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm chosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
->param('transformations', true, new Boolean(true), 'Are image transformations enabled?', true)

View file

@ -13,6 +13,7 @@ use Utopia\Database\Document;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Query\Cursor;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@ -55,6 +56,8 @@ class XList extends Action
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
->inject('response')
->inject('dbForProject')
->inject('project')
->inject('getLogsDB')
->callback($this->action(...));
}
@ -63,7 +66,9 @@ class XList extends Action
string $search,
bool $includeTotal,
Response $response,
Database $dbForProject
Database $dbForProject,
Document $project,
callable $getLogsDB
) {
try {
$queries = Query::parseQueries($queries);
@ -109,6 +114,45 @@ class XList extends Action
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
if (!empty($buckets)) {
$bucketByStatsId = [];
$dbForLogs = call_user_func($getLogsDB, $project);
foreach ($buckets as $bucket) {
$metric = str_replace(
'{bucketInternalId}',
$bucket->getSequence(),
METRIC_BUCKET_ID_FILES_STORAGE
);
$statId = md5('_inf_' . $metric);
$bucketByStatsId[$statId] = $bucket;
// set a default
$bucket->setAttribute('totalSize', 0);
}
/* @type Document[] $stats */
$stats = Authorization::skip(function () use ($dbForLogs, $bucketByStatsId) {
$statsIds = array_keys($bucketByStatsId);
return $dbForLogs->find('stats', [
Query::equal('$id', $statsIds),
Query::select(['value']),
]);
});
foreach ($stats as $stat) {
$bucket = $bucketByStatsId[$stat->getId()];
if ($bucket) {
$bucket->setAttribute('totalSize', $stat->getAttribute('value', 0));
}
}
}
$response->dynamic(new Document([
'buckets' => $buckets,
'total' => $total,

View file

@ -187,7 +187,7 @@ class Deletes extends Action
case DELETE_TYPE_MAINTENANCE:
$this->deleteExpiredTargets($project, $getProjectDB);
$this->deleteExecutionLogs($project, $getProjectDB, $executionRetention);
$this->deleteAuditLogs($project, $getProjectDB, $auditRetention);
$this->deleteAuditLogs($project, $getAudit, $auditRetention);
$this->deleteUsageStats($project, $getProjectDB, $getLogsDB, $hourlyUsageRetentionDatetime);
$this->deleteExpiredSessions($project, $getProjectDB);
$this->deleteExpiredTransactions($project, $getProjectDB);
@ -516,125 +516,136 @@ class Deletes extends Action
$dsn = new DSN('mysql://' . $document->getAttribute('database', 'console'));
}
$dbForProject = $getProjectDB($document);
$projectCollectionIds = [
...\array_keys(Config::getParam('collections', [])['projects']),
SQL::COLLECTION,
AbuseDatabase::COLLECTION,
];
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
$projectTables = !\in_array($dsn->getHost(), $sharedTables);
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
/**
* @var $dbForProject Database
*/
$dbForProject->foreach(Database::METADATA, function (Document $collection) use ($dbForProject, $projectTables, $projectCollectionIds) {
try {
if ($projectTables || !\in_array($collection->getId(), $projectCollectionIds)) {
$dbForProject->deleteCollection($collection->getId());
} else {
$this->deleteByGroup(
$collection->getId(),
[
Query::orderAsc()
],
database: $dbForProject
);
$dbForProject = $getProjectDB($document);
try {
/**
* Disable validation because of Cursor validation on $id underscores
*/
$dbForProject->disableValidation();
$projectCollectionIds = [
...\array_keys(Config::getParam('collections', [])['projects']),
SQL::COLLECTION,
AbuseDatabase::COLLECTION,
];
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
$projectTables = !\in_array($dsn->getHost(), $sharedTables);
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
$dbForProject->foreach(Database::METADATA, function (Document $collection) use ($dbForProject, $projectTables, $projectCollectionIds) {
try {
if ($projectTables || !\in_array($collection->getId(), $projectCollectionIds)) {
$dbForProject->deleteCollection($collection->getId());
} else {
$this->deleteByGroup(
$collection->getId(),
[
Query::orderAsc()
],
database: $dbForProject
);
}
} catch (Throwable $e) {
Console::error('Error deleting ' . $collection->getId() . ' ' . $e->getMessage());
}
} catch (Throwable $e) {
Console::error('Error deleting ' . $collection->getId() . ' ' . $e->getMessage());
});
// Delete Platforms
$this->deleteByGroup('platforms', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete project and function rules
$this->deleteByGroup('rules', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) {
$this->deleteRule($dbForPlatform, $document, $certificates);
});
// Delete Keys
$this->deleteByGroup('keys', [
Query::equal('resourceType', ['projects']),
Query::equal('resourceInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete Webhooks
$this->deleteByGroup('webhooks', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS Installations
$this->deleteByGroup('installations', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS Repositories
$this->deleteByGroup('repositories', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS comments
$this->deleteByGroup('vcsComments', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete Schedules
$this->deleteByGroup('schedules', [
Query::equal('projectId', [$projectId]),
Query::orderAsc()
], $dbForPlatform);
// Delete metadata table
if ($projectTables) {
$dbForProject->deleteCollection(Database::METADATA);
} elseif ($sharedTablesV1) {
$this->deleteByGroup(
Database::METADATA,
[
Query::orderAsc()
],
$dbForProject
);
} elseif ($sharedTablesV2) {
$queries = \array_map(
fn ($id) => Query::notEqual('$id', $id),
$projectCollectionIds
);
$queries[] = Query::orderAsc();
$this->deleteByGroup(
Database::METADATA,
$queries,
$dbForProject
);
}
});
// Delete Platforms
$this->deleteByGroup('platforms', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete all storage directories
$deviceForFiles->delete($deviceForFiles->getRoot(), true);
$deviceForSites->delete($deviceForSites->getRoot(), true);
$deviceForFunctions->delete($deviceForFunctions->getRoot(), true);
$deviceForBuilds->delete($deviceForBuilds->getRoot(), true);
$deviceForCache->delete($deviceForCache->getRoot(), true);
// Delete project and function rules
$this->deleteByGroup('rules', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) {
$this->deleteRule($dbForPlatform, $document, $certificates);
});
// Delete Keys
$this->deleteByGroup('keys', [
Query::equal('resourceType', ['projects']),
Query::equal('resourceInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete Webhooks
$this->deleteByGroup('webhooks', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS Installations
$this->deleteByGroup('installations', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS Repositories
$this->deleteByGroup('repositories', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS comments
$this->deleteByGroup('vcsComments', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete Schedules
$this->deleteByGroup('schedules', [
Query::equal('projectId', [$projectId]),
Query::orderAsc()
], $dbForPlatform);
// Delete metadata table
if ($projectTables) {
$dbForProject->deleteCollection(Database::METADATA);
} elseif ($sharedTablesV1) {
$this->deleteByGroup(
Database::METADATA,
[
Query::orderAsc()
],
$dbForProject
);
} elseif ($sharedTablesV2) {
$queries = \array_map(
fn ($id) => Query::notEqual('$id', $id),
$projectCollectionIds
);
$queries[] = Query::orderAsc();
$this->deleteByGroup(
Database::METADATA,
$queries,
$dbForProject
);
} finally {
$dbForProject->enableValidation();
}
// Delete all storage directories
$deviceForFiles->delete($deviceForFiles->getRoot(), true);
$deviceForSites->delete($deviceForSites->getRoot(), true);
$deviceForFunctions->delete($deviceForFunctions->getRoot(), true);
$deviceForBuilds->delete($deviceForBuilds->getRoot(), true);
$deviceForCache->delete($deviceForCache->getRoot(), true);
}
/**

View file

@ -110,10 +110,18 @@ class Migrations extends Action
$events = $payload['events'] ?? [];
$migration = new Document($payload['migration'] ?? []);
if ($migration->isEmpty()) {
throw new \Exception('Migration not found');
}
if ($project->getId() === 'console') {
return;
}
if ($project->isEmpty()) {
throw new \Exception('Project not found');
}
$this->dbForProject = $dbForProject;
$this->dbForPlatform = $dbForPlatform;
$this->project = $project;
@ -312,7 +320,8 @@ class Migrations extends Action
Mail $queueForMails,
array $platform,
): void {
$project = $this->dbForPlatform->getDocument('projects', $this->project->getId());
$project = $this->project;
$tempAPIKey = $this->generateAPIKey($project);
$transfer = $source = $destination = null;
@ -386,62 +395,59 @@ class Migrations extends Action
Console::error('Line: ' . $th->getLine());
Console::error($th->getTraceAsString());
if (! $migration->isEmpty()) {
$migration->setAttribute('status', 'failed');
$migration->setAttribute('stage', 'finished');
$migration->setAttribute('status', 'failed');
$migration->setAttribute('stage', 'finished');
call_user_func($this->logError, $th, 'appwrite-worker', 'appwrite-queue-'.self::getName(), [
'migrationId' => $migration->getId(),
'source' => $migration->getAttribute('source') ?? '',
'destination' => $migration->getAttribute('destination') ?? '',
]);
call_user_func($this->logError, $th, 'appwrite-worker', 'appwrite-queue-'.self::getName(), [
'migrationId' => $migration->getId(),
'source' => $migration->getAttribute('source') ?? '',
'destination' => $migration->getAttribute('destination') ?? '',
]);
return;
}
if ($transfer) {
$sourceErrors = $source->getErrors();
$destinationErrors = $destination->getErrors();
$migration->setAttribute('errors', $this->sanitizeErrors($sourceErrors, $destinationErrors));
}
} finally {
$this->updateMigrationDocument($migration, $project, $queueForRealtime);
try {
$this->updateMigrationDocument($migration, $project, $queueForRealtime);
if ($migration->getAttribute('status', '') === 'failed') {
Console::error('Migration('.$migration->getSequence().':'.$migration->getId().') failed, Project('.$this->project->getSequence().':'.$this->project->getId().')');
if ($migration->getAttribute('status', '') === 'failed') {
Console::error('Migration('.$migration->getSequence().':'.$migration->getId().') failed, Project('.$this->project->getSequence().':'.$this->project->getId().')');
$sourceErrors = $source?->getErrors() ?? [];
$destinationErrors = $destination?->getErrors() ?? [];
$sourceErrors = $source?->getErrors() ?? [];
$destinationErrors = $destination?->getErrors() ?? [];
foreach ([...$sourceErrors, ...$destinationErrors] as $error) {
/** @var MigrationException $error */
if ($error->getCode() === 0 || $error->getCode() >= 500) {
($this->logError)($error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [
'migrationId' => $migration->getId(),
'source' => $migration->getAttribute('source') ?? '',
'destination' => $migration->getAttribute('destination') ?? '',
'resourceName' => $error->getResourceName(),
'resourceGroup' => $error->getResourceGroup(),
]);
foreach ([...$sourceErrors, ...$destinationErrors] as $error) {
/** @var MigrationException $error */
if ($error->getCode() === 0 || $error->getCode() >= 500) {
($this->logError)($error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [
'migrationId' => $migration->getId(),
'source' => $migration->getAttribute('source') ?? '',
'destination' => $migration->getAttribute('destination') ?? '',
'resourceName' => $error->getResourceName(),
'resourceGroup' => $error->getResourceGroup(),
]);
}
}
$source?->error();
$destination?->error();
}
if ($migration->getAttribute('status', '') === 'completed') {
$destination?->success();
$source?->success();
// todo: Move to CSV hook
if ($migration->getAttribute('destination') === DestinationCSV::getName()) {
$this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform);
}
}
} finally {
$source?->cleanUp();
$destination?->cleanUp();
$source?->error();
$destination?->error();
$transfer = null;
$source = null;
$destination = null;
}
if ($migration->getAttribute('status', '') === 'completed') {
$destination?->success();
$source?->success();
if ($migration->getAttribute('destination') === DestinationCSV::getName()) {
$this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform);
}
}
$transfer = null;
$source = null;
$destination = null;
}
}

View file

@ -8,6 +8,7 @@ class Projects extends Base
'name',
'teamId',
'labels',
'search'
];
/**

View file

@ -69,7 +69,7 @@ class Bucket extends Model
])
->addRule('compression', [
'type' => self::TYPE_STRING,
'description' => 'Compression algorithm choosen for compression. Will be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd).',
'description' => 'Compression algorithm chosen for compression. Will be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd).',
'default' => '',
'example' => 'gzip',
'array' => false
@ -92,6 +92,12 @@ class Bucket extends Model
'default' => true,
'example' => false,
])
->addRule('totalSize', [
'type' => self::TYPE_INTEGER,
'description' => 'Total size of this bucket in bytes.',
'default' => 0,
'example' => 128,
])
;
}

View file

@ -2334,7 +2334,8 @@ trait Base
buckets {
_id
name
enabled
enabled,
totalSize
}
}
}';
@ -2344,6 +2345,7 @@ trait Base
_id
name
enabled
totalSize
}
}';
case self::UPDATE_BUCKET:

View file

@ -105,12 +105,24 @@ class StorageServerTest extends Scope
$buckets = $buckets['body']['data']['storageListBuckets'];
$this->assertIsArray($buckets);
if (!empty($buckets['buckets'])) {
foreach ($buckets['buckets'] as $bucket) {
$this->assertArrayHasKey('totalSize', $bucket);
$this->assertIsInt($bucket['totalSize']);
/* always 0 because the stats worker runs hourly! */
$this->assertGreaterThanOrEqual(0, $bucket['totalSize']);
}
}
return $buckets;
}
/**
* @depends testCreateBucket
* @depends testCreateFile
* @param $bucket
* @param $file
* @return array
* @throws \Exception
*/
@ -134,6 +146,7 @@ class StorageServerTest extends Scope
$this->assertArrayNotHasKey('errors', $bucket['body']);
$bucket = $bucket['body']['data']['storageGetBucket'];
$this->assertEquals('Actors', $bucket['name']);
$this->assertArrayHasKey('totalSize', $bucket);
return $bucket;
}

View file

@ -951,4 +951,69 @@ trait StorageBase
return $data;
}
public function testBucketTotalSize(): void
{
$bucket = $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 Size',
'permissions' => [
Permission::read(Role::any()),
Permission::create(Role::any()),
],
]);
$this->assertEquals(201, $bucket['headers']['status-code']);
$bucketId = $bucket['body']['$id'];
// bucket should have totalSize = 0 (no files)
$emptyBucket = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]);
$this->assertEquals(200, $emptyBucket['headers']['status-code']);
$this->assertArrayHasKey('totalSize', $emptyBucket['body']);
$this->assertEquals(0, $emptyBucket['body']['totalSize']);
// upload first file
$file1 = $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'),
]);
$this->assertEquals(201, $file1['headers']['status-code']);
// upload second file
$file2 = $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/image.webp'), 'image/webp', 'image.webp'),
]);
$this->assertEquals(201, $file2['headers']['status-code']);
$bucket = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]);
$this->assertEquals(200, $bucket['headers']['status-code']);
$this->assertArrayHasKey('totalSize', $bucket['body']);
$this->assertIsInt($bucket['body']['totalSize']);
/* will always be 0 in tests because the worker runs hourly! */
$this->assertGreaterThanOrEqual(0, $bucket['body']['totalSize']);
}
}

View file

@ -96,6 +96,14 @@ class StorageCustomServerTest extends Scope
$this->assertEquals($id, $response['body']['buckets'][0]['$id']);
$this->assertEquals('Test Bucket', $response['body']['buckets'][0]['name']);
foreach ($response['body']['buckets'] as $bucket) {
$this->assertArrayHasKey('totalSize', $bucket);
$this->assertIsInt($bucket['totalSize']);
/* always 0 because the stats worker runs hourly! */
$this->assertGreaterThanOrEqual(0, $bucket['totalSize']);
}
$response = $this->client->call(Client::METHOD_GET, '/storage/buckets', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -186,6 +194,7 @@ class StorageCustomServerTest extends Scope
$this->assertNotEmpty($response['body']);
$this->assertEquals($id, $response['body']['$id']);
$this->assertEquals('Test Bucket', $response['body']['name']);
$this->assertArrayHasKey('totalSize', $response['body']);
/**
* Test for FAILURE