mirror of
https://github.com/appwrite/appwrite
synced 2026-05-20 23:48:23 +00:00
Merge branch 'feat-sites' into feat-add-detection-logic
This commit is contained in:
commit
34b8453666
21 changed files with 1712 additions and 943 deletions
|
|
@ -5033,7 +5033,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"weight": 326,
|
||||
"weight": 324,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -5084,7 +5084,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"weight": 325,
|
||||
"weight": 323,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -5543,7 +5543,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"weight": 371,
|
||||
"weight": 369,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5625,7 +5625,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"weight": 375,
|
||||
"weight": 373,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -8138,7 +8138,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"weight": 389,
|
||||
"weight": 387,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -8211,7 +8211,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"weight": 387,
|
||||
"weight": 385,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -8402,26 +8402,6 @@
|
|||
"description": "Path to function code in the linked repo.",
|
||||
"x-example": "<PROVIDER_ROOT_DIRECTORY>"
|
||||
},
|
||||
"templateRepository": {
|
||||
"type": "string",
|
||||
"description": "Repository name of the template.",
|
||||
"x-example": "<TEMPLATE_REPOSITORY>"
|
||||
},
|
||||
"templateOwner": {
|
||||
"type": "string",
|
||||
"description": "The name of the owner of the template.",
|
||||
"x-example": "<TEMPLATE_OWNER>"
|
||||
},
|
||||
"templateRootDirectory": {
|
||||
"type": "string",
|
||||
"description": "Path to function code in the template repo.",
|
||||
"x-example": "<TEMPLATE_ROOT_DIRECTORY>"
|
||||
},
|
||||
"templateVersion": {
|
||||
"type": "string",
|
||||
"description": "Version (tag) for the repo linked to the function template.",
|
||||
"x-example": "<TEMPLATE_VERSION>"
|
||||
},
|
||||
"specification": {
|
||||
"type": "string",
|
||||
"description": "Runtime specification for the function and builds.",
|
||||
|
|
@ -8461,7 +8441,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listRuntimes",
|
||||
"weight": 390,
|
||||
"weight": 388,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -8619,7 +8599,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "update",
|
||||
"weight": 388,
|
||||
"weight": 386,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -8990,7 +8970,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createDeployment",
|
||||
"weight": 391,
|
||||
"weight": 389,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"deprecated": false,
|
||||
|
|
@ -9064,6 +9044,109 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"\/functions\/{functionId}\/deployments\/template": {
|
||||
"post": {
|
||||
"summary": "Create template deployment",
|
||||
"operationId": "functionsCreateTemplateDeployment",
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Deployment",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/deployment"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTemplateDeployment",
|
||||
"weight": 390,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "functions\/create-template-deployment.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate 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.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "functions.write",
|
||||
"platforms": [
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": [],
|
||||
"Key": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Key": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "functionId",
|
||||
"description": "Function ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<FUNCTION_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"repository": {
|
||||
"type": "string",
|
||||
"description": "Repository name of the template.",
|
||||
"x-example": "<REPOSITORY>"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "The name of the owner of the template.",
|
||||
"x-example": "<OWNER>"
|
||||
},
|
||||
"rootDirectory": {
|
||||
"type": "string",
|
||||
"description": "Path to function code in the template repo.",
|
||||
"x-example": "<ROOT_DIRECTORY>"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Version (tag) for the repo linked to the function template.",
|
||||
"x-example": "<VERSION>"
|
||||
},
|
||||
"activate": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically activate the deployment when it is finished building.",
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"repository",
|
||||
"owner",
|
||||
"rootDirectory",
|
||||
"version"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"\/functions\/{functionId}\/deployments\/{deploymentId}": {
|
||||
"get": {
|
||||
"summary": "Get deployment",
|
||||
|
|
@ -9819,7 +9902,7 @@
|
|||
},
|
||||
"secret": {
|
||||
"type": "boolean",
|
||||
"description": "Is secret? Secret variables can only be updated or deleted, they cannot be read.",
|
||||
"description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.",
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
|
|
@ -9855,7 +9938,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"weight": 326,
|
||||
"weight": 324,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -9908,7 +9991,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"weight": 325,
|
||||
"weight": 323,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -11680,7 +11763,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listMessages",
|
||||
"weight": 379,
|
||||
"weight": 377,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -11756,7 +11839,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createEmail",
|
||||
"weight": 376,
|
||||
"weight": 374,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -11900,7 +11983,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateEmail",
|
||||
"weight": 383,
|
||||
"weight": 381,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12046,7 +12129,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createPush",
|
||||
"weight": 378,
|
||||
"weight": 376,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12220,7 +12303,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updatePush",
|
||||
"weight": 385,
|
||||
"weight": 383,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12398,7 +12481,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSms",
|
||||
"weight": 377,
|
||||
"weight": 375,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12507,7 +12590,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateSms",
|
||||
"weight": 384,
|
||||
"weight": 382,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12619,7 +12702,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "getMessage",
|
||||
"weight": 382,
|
||||
"weight": 380,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12672,7 +12755,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"weight": 386,
|
||||
"weight": 384,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12734,7 +12817,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listMessageLogs",
|
||||
"weight": 380,
|
||||
"weight": 378,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12809,7 +12892,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listTargets",
|
||||
"weight": 381,
|
||||
"weight": 379,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12884,7 +12967,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listProviders",
|
||||
"weight": 351,
|
||||
"weight": 349,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12960,7 +13043,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createApnsProvider",
|
||||
"weight": 350,
|
||||
"weight": 348,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13065,7 +13148,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateApnsProvider",
|
||||
"weight": 363,
|
||||
"weight": 361,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13173,7 +13256,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createFcmProvider",
|
||||
"weight": 349,
|
||||
"weight": 347,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13258,7 +13341,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateFcmProvider",
|
||||
"weight": 362,
|
||||
"weight": 360,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13346,7 +13429,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createMailgunProvider",
|
||||
"weight": 341,
|
||||
"weight": 339,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13461,7 +13544,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateMailgunProvider",
|
||||
"weight": 354,
|
||||
"weight": 352,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13579,7 +13662,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createMsg91Provider",
|
||||
"weight": 344,
|
||||
"weight": 342,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13674,7 +13757,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateMsg91Provider",
|
||||
"weight": 357,
|
||||
"weight": 355,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13772,7 +13855,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSendgridProvider",
|
||||
"weight": 342,
|
||||
"weight": 340,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13877,7 +13960,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateSendgridProvider",
|
||||
"weight": 355,
|
||||
"weight": 353,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13985,7 +14068,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSmtpProvider",
|
||||
"weight": 343,
|
||||
"weight": 341,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14128,7 +14211,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateSmtpProvider",
|
||||
"weight": 356,
|
||||
"weight": 354,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14273,7 +14356,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTelesignProvider",
|
||||
"weight": 345,
|
||||
"weight": 343,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14368,7 +14451,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateTelesignProvider",
|
||||
"weight": 358,
|
||||
"weight": 356,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14466,7 +14549,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTextmagicProvider",
|
||||
"weight": 346,
|
||||
"weight": 344,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14561,7 +14644,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateTextmagicProvider",
|
||||
"weight": 359,
|
||||
"weight": 357,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14659,7 +14742,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTwilioProvider",
|
||||
"weight": 347,
|
||||
"weight": 345,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14754,7 +14837,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateTwilioProvider",
|
||||
"weight": 360,
|
||||
"weight": 358,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14852,7 +14935,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createVonageProvider",
|
||||
"weight": 348,
|
||||
"weight": 346,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14947,7 +15030,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateVonageProvider",
|
||||
"weight": 361,
|
||||
"weight": 359,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15045,7 +15128,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "getProvider",
|
||||
"weight": 353,
|
||||
"weight": 351,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15098,7 +15181,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteProvider",
|
||||
"weight": 364,
|
||||
"weight": 362,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15160,7 +15243,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listProviderLogs",
|
||||
"weight": 352,
|
||||
"weight": 350,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15235,7 +15318,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listSubscriberLogs",
|
||||
"weight": 373,
|
||||
"weight": 371,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15310,7 +15393,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listTopics",
|
||||
"weight": 366,
|
||||
"weight": 364,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15384,7 +15467,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTopic",
|
||||
"weight": 365,
|
||||
"weight": 363,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15467,7 +15550,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "getTopic",
|
||||
"weight": 368,
|
||||
"weight": 366,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15527,7 +15610,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateTopic",
|
||||
"weight": 369,
|
||||
"weight": 367,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15604,7 +15687,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteTopic",
|
||||
"weight": 370,
|
||||
"weight": 368,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15666,7 +15749,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listTopicLogs",
|
||||
"weight": 367,
|
||||
"weight": 365,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15741,7 +15824,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listSubscribers",
|
||||
"weight": 372,
|
||||
"weight": 370,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15825,7 +15908,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"weight": 371,
|
||||
"weight": 369,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15916,7 +15999,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "getSubscriber",
|
||||
"weight": 374,
|
||||
"weight": 372,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15979,7 +16062,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"weight": 375,
|
||||
"weight": 373,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16055,7 +16138,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"weight": 394,
|
||||
"weight": 393,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16125,7 +16208,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"weight": 392,
|
||||
"weight": 391,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16207,11 +16290,6 @@
|
|||
"description": "Output Directory for site.",
|
||||
"x-example": "<OUTPUT_DIRECTORY>"
|
||||
},
|
||||
"subdomain": {
|
||||
"type": "string",
|
||||
"description": "Unique custom sub-domain. 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.",
|
||||
"x-example": "<SUBDOMAIN>"
|
||||
},
|
||||
"buildRuntime": {
|
||||
"type": "string",
|
||||
"description": "Runtime to use during build step.",
|
||||
|
|
@ -16318,26 +16396,6 @@
|
|||
"description": "Path to site code in the linked repo.",
|
||||
"x-example": "<PROVIDER_ROOT_DIRECTORY>"
|
||||
},
|
||||
"templateRepository": {
|
||||
"type": "string",
|
||||
"description": "Repository name of the template.",
|
||||
"x-example": "<TEMPLATE_REPOSITORY>"
|
||||
},
|
||||
"templateOwner": {
|
||||
"type": "string",
|
||||
"description": "The name of the owner of the template.",
|
||||
"x-example": "<TEMPLATE_OWNER>"
|
||||
},
|
||||
"templateRootDirectory": {
|
||||
"type": "string",
|
||||
"description": "Path to site code in the template repo.",
|
||||
"x-example": "<TEMPLATE_ROOT_DIRECTORY>"
|
||||
},
|
||||
"templateVersion": {
|
||||
"type": "string",
|
||||
"description": "Version (tag) for the repo linked to the site template.",
|
||||
"x-example": "<TEMPLATE_VERSION>"
|
||||
},
|
||||
"specification": {
|
||||
"type": "string",
|
||||
"description": "Framework specification for the site and builds.",
|
||||
|
|
@ -16378,7 +16436,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listFrameworks",
|
||||
"weight": 397,
|
||||
"weight": 396,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16427,7 +16485,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"weight": 393,
|
||||
"weight": 392,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16486,7 +16544,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "update",
|
||||
"weight": 395,
|
||||
"weight": 394,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16710,7 +16768,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"weight": 396,
|
||||
"weight": 395,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16854,7 +16912,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createDeployment",
|
||||
"weight": 398,
|
||||
"weight": 397,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"deprecated": false,
|
||||
|
|
@ -16933,6 +16991,109 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"\/sites\/{siteId}\/deployments\/template": {
|
||||
"post": {
|
||||
"summary": "Create deployment",
|
||||
"operationId": "sitesCreateTemplateDeployment",
|
||||
"tags": [
|
||||
"sites"
|
||||
],
|
||||
"description": "",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Deployment",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/deployment"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTemplateDeployment",
|
||||
"weight": 398,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "sites\/create-template-deployment.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate 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.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "sites.write",
|
||||
"platforms": [
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": [],
|
||||
"Key": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Key": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "siteId",
|
||||
"description": "Site ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<SITE_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"repository": {
|
||||
"type": "string",
|
||||
"description": "Repository name of the template.",
|
||||
"x-example": "<REPOSITORY>"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "The name of the owner of the template.",
|
||||
"x-example": "<OWNER>"
|
||||
},
|
||||
"rootDirectory": {
|
||||
"type": "string",
|
||||
"description": "Path to site code in the template repo.",
|
||||
"x-example": "<ROOT_DIRECTORY>"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Version (tag) for the repo linked to the site template.",
|
||||
"x-example": "<VERSION>"
|
||||
},
|
||||
"activate": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically activate the deployment when it is finished building.",
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"repository",
|
||||
"owner",
|
||||
"rootDirectory",
|
||||
"version"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"\/sites\/{siteId}\/deployments\/{deploymentId}": {
|
||||
"get": {
|
||||
"summary": "Get deployment",
|
||||
|
|
@ -17751,7 +17912,7 @@
|
|||
},
|
||||
"secret": {
|
||||
"type": "boolean",
|
||||
"description": "Is secret? Secret variables can only be updated or deleted, they cannot be read.",
|
||||
"description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.",
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
|
|
@ -17918,6 +18079,11 @@
|
|||
"type": "string",
|
||||
"description": "Variable value. Max length: 8192 chars.",
|
||||
"x-example": "<VALUE>"
|
||||
},
|
||||
"secret": {
|
||||
"type": "boolean",
|
||||
"description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.",
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
|||
|
|
@ -5198,7 +5198,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"weight": 326,
|
||||
"weight": 324,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -5271,7 +5271,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"weight": 325,
|
||||
"weight": 323,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -5768,7 +5768,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"weight": 371,
|
||||
"weight": 369,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5852,7 +5852,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"weight": 375,
|
||||
"weight": 373,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -8284,7 +8284,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"weight": 389,
|
||||
"weight": 387,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -8356,7 +8356,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"weight": 387,
|
||||
"weight": 385,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -8565,30 +8565,6 @@
|
|||
"default": "",
|
||||
"x-example": "<PROVIDER_ROOT_DIRECTORY>"
|
||||
},
|
||||
"templateRepository": {
|
||||
"type": "string",
|
||||
"description": "Repository name of the template.",
|
||||
"default": "",
|
||||
"x-example": "<TEMPLATE_REPOSITORY>"
|
||||
},
|
||||
"templateOwner": {
|
||||
"type": "string",
|
||||
"description": "The name of the owner of the template.",
|
||||
"default": "",
|
||||
"x-example": "<TEMPLATE_OWNER>"
|
||||
},
|
||||
"templateRootDirectory": {
|
||||
"type": "string",
|
||||
"description": "Path to function code in the template repo.",
|
||||
"default": "",
|
||||
"x-example": "<TEMPLATE_ROOT_DIRECTORY>"
|
||||
},
|
||||
"templateVersion": {
|
||||
"type": "string",
|
||||
"description": "Version (tag) for the repo linked to the function template.",
|
||||
"default": "",
|
||||
"x-example": "<TEMPLATE_VERSION>"
|
||||
},
|
||||
"specification": {
|
||||
"type": "string",
|
||||
"description": "Runtime specification for the function and builds.",
|
||||
|
|
@ -8630,7 +8606,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listRuntimes",
|
||||
"weight": 390,
|
||||
"weight": 388,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -8792,7 +8768,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "update",
|
||||
"weight": 388,
|
||||
"weight": 386,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -9177,7 +9153,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createDeployment",
|
||||
"weight": 391,
|
||||
"weight": 389,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"deprecated": false,
|
||||
|
|
@ -9245,6 +9221,112 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"\/functions\/{functionId}\/deployments\/template": {
|
||||
"post": {
|
||||
"summary": "Create template deployment",
|
||||
"operationId": "functionsCreateTemplateDeployment",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Deployment",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/deployment"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTemplateDeployment",
|
||||
"weight": 390,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "functions\/create-template-deployment.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate 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.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "functions.write",
|
||||
"platforms": [
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": [],
|
||||
"Key": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Key": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "functionId",
|
||||
"description": "Function ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<FUNCTION_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"repository": {
|
||||
"type": "string",
|
||||
"description": "Repository name of the template.",
|
||||
"default": null,
|
||||
"x-example": "<REPOSITORY>"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "The name of the owner of the template.",
|
||||
"default": null,
|
||||
"x-example": "<OWNER>"
|
||||
},
|
||||
"rootDirectory": {
|
||||
"type": "string",
|
||||
"description": "Path to function code in the template repo.",
|
||||
"default": null,
|
||||
"x-example": "<ROOT_DIRECTORY>"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Version (tag) for the repo linked to the function template.",
|
||||
"default": null,
|
||||
"x-example": "<VERSION>"
|
||||
},
|
||||
"activate": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically activate the deployment when it is finished building.",
|
||||
"default": false,
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"repository",
|
||||
"owner",
|
||||
"rootDirectory",
|
||||
"version"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/functions\/{functionId}\/deployments\/{deploymentId}": {
|
||||
"get": {
|
||||
"summary": "Get deployment",
|
||||
|
|
@ -10004,8 +10086,8 @@
|
|||
},
|
||||
"secret": {
|
||||
"type": "boolean",
|
||||
"description": "Is secret? Secret variables can only be updated or deleted, they cannot be read.",
|
||||
"default": false,
|
||||
"description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.",
|
||||
"default": true,
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
|
|
@ -10042,7 +10124,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"weight": 326,
|
||||
"weight": 324,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -10117,7 +10199,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"weight": 325,
|
||||
"weight": 323,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -11939,7 +12021,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listMessages",
|
||||
"weight": 379,
|
||||
"weight": 377,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12014,7 +12096,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createEmail",
|
||||
"weight": 376,
|
||||
"weight": 374,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12172,7 +12254,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateEmail",
|
||||
"weight": 383,
|
||||
"weight": 381,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12327,7 +12409,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createPush",
|
||||
"weight": 378,
|
||||
"weight": 376,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12522,7 +12604,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updatePush",
|
||||
"weight": 385,
|
||||
"weight": 383,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12716,7 +12798,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSms",
|
||||
"weight": 377,
|
||||
"weight": 375,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12834,7 +12916,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateSms",
|
||||
"weight": 384,
|
||||
"weight": 382,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -12950,7 +13032,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "getMessage",
|
||||
"weight": 382,
|
||||
"weight": 380,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13005,7 +13087,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"weight": 386,
|
||||
"weight": 384,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13067,7 +13149,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listMessageLogs",
|
||||
"weight": 380,
|
||||
"weight": 378,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13141,7 +13223,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listTargets",
|
||||
"weight": 381,
|
||||
"weight": 379,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13215,7 +13297,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listProviders",
|
||||
"weight": 351,
|
||||
"weight": 349,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13290,7 +13372,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createApnsProvider",
|
||||
"weight": 350,
|
||||
"weight": 348,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13405,7 +13487,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateApnsProvider",
|
||||
"weight": 363,
|
||||
"weight": 361,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13518,7 +13600,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createFcmProvider",
|
||||
"weight": 349,
|
||||
"weight": 347,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13609,7 +13691,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateFcmProvider",
|
||||
"weight": 362,
|
||||
"weight": 360,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13698,7 +13780,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createMailgunProvider",
|
||||
"weight": 341,
|
||||
"weight": 339,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13825,7 +13907,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateMailgunProvider",
|
||||
"weight": 354,
|
||||
"weight": 352,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -13950,7 +14032,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createMsg91Provider",
|
||||
"weight": 344,
|
||||
"weight": 342,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14053,7 +14135,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateMsg91Provider",
|
||||
"weight": 357,
|
||||
"weight": 355,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14154,7 +14236,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSendgridProvider",
|
||||
"weight": 342,
|
||||
"weight": 340,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14269,7 +14351,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateSendgridProvider",
|
||||
"weight": 355,
|
||||
"weight": 353,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14382,7 +14464,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSmtpProvider",
|
||||
"weight": 343,
|
||||
"weight": 341,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14541,7 +14623,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateSmtpProvider",
|
||||
"weight": 356,
|
||||
"weight": 354,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14697,7 +14779,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTelesignProvider",
|
||||
"weight": 345,
|
||||
"weight": 343,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14800,7 +14882,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateTelesignProvider",
|
||||
"weight": 358,
|
||||
"weight": 356,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -14901,7 +14983,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTextmagicProvider",
|
||||
"weight": 346,
|
||||
"weight": 344,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15004,7 +15086,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateTextmagicProvider",
|
||||
"weight": 359,
|
||||
"weight": 357,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15105,7 +15187,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTwilioProvider",
|
||||
"weight": 347,
|
||||
"weight": 345,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15208,7 +15290,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateTwilioProvider",
|
||||
"weight": 360,
|
||||
"weight": 358,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15309,7 +15391,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createVonageProvider",
|
||||
"weight": 348,
|
||||
"weight": 346,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15412,7 +15494,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateVonageProvider",
|
||||
"weight": 361,
|
||||
"weight": 359,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15513,7 +15595,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "getProvider",
|
||||
"weight": 353,
|
||||
"weight": 351,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15568,7 +15650,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteProvider",
|
||||
"weight": 364,
|
||||
"weight": 362,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15630,7 +15712,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listProviderLogs",
|
||||
"weight": 352,
|
||||
"weight": 350,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15704,7 +15786,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listSubscriberLogs",
|
||||
"weight": 373,
|
||||
"weight": 371,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15778,7 +15860,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listTopics",
|
||||
"weight": 366,
|
||||
"weight": 364,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15851,7 +15933,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTopic",
|
||||
"weight": 365,
|
||||
"weight": 363,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -15941,7 +16023,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "getTopic",
|
||||
"weight": 368,
|
||||
"weight": 366,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16001,7 +16083,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "updateTopic",
|
||||
"weight": 369,
|
||||
"weight": 367,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16080,7 +16162,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteTopic",
|
||||
"weight": 370,
|
||||
"weight": 368,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16142,7 +16224,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listTopicLogs",
|
||||
"weight": 367,
|
||||
"weight": 365,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16216,7 +16298,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listSubscribers",
|
||||
"weight": 372,
|
||||
"weight": 370,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16297,7 +16379,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"weight": 371,
|
||||
"weight": 369,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16388,7 +16470,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "getSubscriber",
|
||||
"weight": 374,
|
||||
"weight": 372,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16451,7 +16533,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"weight": 375,
|
||||
"weight": 373,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16525,7 +16607,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"weight": 394,
|
||||
"weight": 393,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16597,7 +16679,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"weight": 392,
|
||||
"weight": 391,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16688,12 +16770,6 @@
|
|||
"default": "",
|
||||
"x-example": "<OUTPUT_DIRECTORY>"
|
||||
},
|
||||
"subdomain": {
|
||||
"type": "string",
|
||||
"description": "Unique custom sub-domain. 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.",
|
||||
"default": "",
|
||||
"x-example": "<SUBDOMAIN>"
|
||||
},
|
||||
"buildRuntime": {
|
||||
"type": "string",
|
||||
"description": "Runtime to use during build step.",
|
||||
|
|
@ -16808,30 +16884,6 @@
|
|||
"default": "",
|
||||
"x-example": "<PROVIDER_ROOT_DIRECTORY>"
|
||||
},
|
||||
"templateRepository": {
|
||||
"type": "string",
|
||||
"description": "Repository name of the template.",
|
||||
"default": "",
|
||||
"x-example": "<TEMPLATE_REPOSITORY>"
|
||||
},
|
||||
"templateOwner": {
|
||||
"type": "string",
|
||||
"description": "The name of the owner of the template.",
|
||||
"default": "",
|
||||
"x-example": "<TEMPLATE_OWNER>"
|
||||
},
|
||||
"templateRootDirectory": {
|
||||
"type": "string",
|
||||
"description": "Path to site code in the template repo.",
|
||||
"default": "",
|
||||
"x-example": "<TEMPLATE_ROOT_DIRECTORY>"
|
||||
},
|
||||
"templateVersion": {
|
||||
"type": "string",
|
||||
"description": "Version (tag) for the repo linked to the site template.",
|
||||
"default": "",
|
||||
"x-example": "<TEMPLATE_VERSION>"
|
||||
},
|
||||
"specification": {
|
||||
"type": "string",
|
||||
"description": "Framework specification for the site and builds.",
|
||||
|
|
@ -16874,7 +16926,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "listFrameworks",
|
||||
"weight": 397,
|
||||
"weight": 396,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16925,7 +16977,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"weight": 393,
|
||||
"weight": 392,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -16984,7 +17036,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "update",
|
||||
"weight": 395,
|
||||
"weight": 394,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -17224,7 +17276,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"weight": 396,
|
||||
"weight": 395,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -17365,7 +17417,7 @@
|
|||
},
|
||||
"x-appwrite": {
|
||||
"method": "createDeployment",
|
||||
"weight": 398,
|
||||
"weight": 397,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"deprecated": false,
|
||||
|
|
@ -17441,6 +17493,112 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"\/sites\/{siteId}\/deployments\/template": {
|
||||
"post": {
|
||||
"summary": "Create deployment",
|
||||
"operationId": "sitesCreateTemplateDeployment",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"sites"
|
||||
],
|
||||
"description": "",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Deployment",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/deployment"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createTemplateDeployment",
|
||||
"weight": 398,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "sites\/create-template-deployment.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate 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.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "sites.write",
|
||||
"platforms": [
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": [],
|
||||
"Key": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Key": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "siteId",
|
||||
"description": "Site ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<SITE_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"repository": {
|
||||
"type": "string",
|
||||
"description": "Repository name of the template.",
|
||||
"default": null,
|
||||
"x-example": "<REPOSITORY>"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "The name of the owner of the template.",
|
||||
"default": null,
|
||||
"x-example": "<OWNER>"
|
||||
},
|
||||
"rootDirectory": {
|
||||
"type": "string",
|
||||
"description": "Path to site code in the template repo.",
|
||||
"default": null,
|
||||
"x-example": "<ROOT_DIRECTORY>"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Version (tag) for the repo linked to the site template.",
|
||||
"default": null,
|
||||
"x-example": "<VERSION>"
|
||||
},
|
||||
"activate": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically activate the deployment when it is finished building.",
|
||||
"default": false,
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"repository",
|
||||
"owner",
|
||||
"rootDirectory",
|
||||
"version"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/sites\/{siteId}\/deployments\/{deploymentId}": {
|
||||
"get": {
|
||||
"summary": "Get deployment",
|
||||
|
|
@ -18266,8 +18424,8 @@
|
|||
},
|
||||
"secret": {
|
||||
"type": "boolean",
|
||||
"description": "Is secret? Secret variables can only be updated or deleted, they cannot be read.",
|
||||
"default": false,
|
||||
"description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.",
|
||||
"default": true,
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
|
|
@ -18430,6 +18588,12 @@
|
|||
"description": "Variable value. Max length: 8192 chars.",
|
||||
"default": null,
|
||||
"x-example": "<VALUE>"
|
||||
},
|
||||
"secret": {
|
||||
"type": "boolean",
|
||||
"description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.",
|
||||
"default": null,
|
||||
"x-example": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
|||
|
|
@ -15,176 +15,13 @@ use Utopia\App;
|
|||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Domain as ValidatorDomain;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
App::post('/v1/proxy/rules')
|
||||
->groups(['api', 'proxy'])
|
||||
->desc('Create rule')
|
||||
->label('scope', 'rules.write')
|
||||
->label('event', 'rules.[ruleId].create')
|
||||
->label('audits.event', 'rule.create')
|
||||
->label('audits.resource', 'rule/{response.$id}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'proxy',
|
||||
name: 'createRule',
|
||||
description: '/docs/references/proxy/create-rule.md',
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_CREATED,
|
||||
model: Response::MODEL_PROXY_RULE,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('domain', null, new ValidatorDomain(), 'Domain name.')
|
||||
->param('resourceType', null, new WhiteList(['api', 'function', 'site']), 'Action definition for the rule. Possible values are "api", "function" and "site"')
|
||||
->param('resourceId', '', new UID(), 'ID of resource for the action type. If resourceType is "api", leave empty. If resourceType is "function", provide ID of the function.', true)
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('queueForCertificates')
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForPlatform')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $domain, string $resourceType, string $resourceId, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) {
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
if ($domain === $mainDomain) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your main domain to specific resource. Please use subdomain or a different domain.');
|
||||
}
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
if (
|
||||
($functionsDomain !== '' && str_ends_with($domain, $functionsDomain)) ||
|
||||
($sitesDomain !== '' && str_ends_with($domain, $sitesDomain))
|
||||
) {
|
||||
// TODO: Refactor later
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions or sites domain or their subdomains to a specific resource. Please use a different domain.');
|
||||
}
|
||||
|
||||
if ($domain === 'localhost' || $domain === APP_HOSTNAME_INTERNAL) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.');
|
||||
}
|
||||
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
|
||||
$document = $dbForPlatform->getDocument('rules', md5($domain));
|
||||
} else {
|
||||
$document = $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$domain]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if (!$document->isEmpty()) {
|
||||
if ($document->getAttribute('projectId') === $project->getId()) {
|
||||
$resourceType = $document->getAttribute('resourceType');
|
||||
$resourceId = $document->getAttribute('resourceId');
|
||||
$message = "Domain already assigned to '{$resourceType}' service";
|
||||
if (!empty($resourceId)) {
|
||||
$message .= " with ID '{$resourceId}'";
|
||||
}
|
||||
|
||||
$message .= '.';
|
||||
} else {
|
||||
$message = 'Domain already assigned to different project.';
|
||||
}
|
||||
|
||||
throw new Exception(Exception::RULE_ALREADY_EXISTS, $message);
|
||||
}
|
||||
|
||||
$resourceInternalId = '';
|
||||
|
||||
switch ($resourceType) {
|
||||
case 'function':
|
||||
if (empty($resourceId)) {
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $resourceId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$resourceInternalId = $function->getInternalId();
|
||||
break;
|
||||
case 'site':
|
||||
if (empty($resourceId)) {
|
||||
throw new Exception(Exception::SITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$site = $dbForProject->getDocument('sites', $resourceId);
|
||||
|
||||
if ($site->isEmpty()) {
|
||||
throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$resourceInternalId = $site->getInternalId();
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
$domain = new Domain($domain);
|
||||
} catch (\Throwable) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.');
|
||||
}
|
||||
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
||||
|
||||
$rule = new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
'domain' => $domain->get(),
|
||||
'resourceType' => $resourceType,
|
||||
'resourceId' => $resourceId,
|
||||
'resourceInternalId' => $resourceInternalId,
|
||||
'certificateId' => '',
|
||||
]);
|
||||
|
||||
$status = 'created';
|
||||
|
||||
if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) {
|
||||
$status = 'verified';
|
||||
}
|
||||
|
||||
if ($status === 'created') {
|
||||
$target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
$validator = new CNAME($target->get()); // Verify Domain with DNS records
|
||||
|
||||
if ($validator->isValid($domain->get())) {
|
||||
$status = 'verifying';
|
||||
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain')
|
||||
]))
|
||||
->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
$rule->setAttribute('status', $status);
|
||||
$rule = $dbForPlatform->createDocument('rules', $rule);
|
||||
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
$rule->setAttribute('logs', '');
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
});
|
||||
|
||||
App::get('/v1/proxy/rules')
|
||||
->groups(['api', 'proxy'])
|
||||
|
|
@ -411,34 +248,3 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
|
|||
|
||||
$response->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
});
|
||||
|
||||
App::get('/v1/proxy/subdomains')
|
||||
->desc('Check if subdomain is available')
|
||||
->groups(['api', 'proxy'])
|
||||
->label('scope', 'rules.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'proxy')
|
||||
->label('sdk.method', 'checkSubdomain')
|
||||
->label('sdk.description', '/docs/references/proxy/check-subdomain.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->param('resourceType', null, new WhiteList(['function', 'site']), 'Action definition for the rule. Possible values are "function" and "site"')
|
||||
->param('subdomain', '', new Text(256), 'Subdomain name.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $resourceType, string $subdomain, Response $response, Database $dbForPlatform) {
|
||||
//TODO: Add tests for this endpoint
|
||||
$resourceDomain = $resourceType === 'site' ? System::getEnv('_APP_DOMAIN_SITES', '') : System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
$domain = $subdomain . '.' . $resourceDomain;
|
||||
|
||||
$document = $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$domain]),
|
||||
]);
|
||||
|
||||
if ($document && !$document->isEmpty()) {
|
||||
throw new Exception(Exception::RULE_ALREADY_EXISTS, 'Subdomain already assigned to different project.');
|
||||
}
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -737,9 +737,19 @@ App::init()
|
|||
$validator = new Hostname($clients);
|
||||
if ($validator->isValid($origin)) {
|
||||
$refDomainOrigin = $origin;
|
||||
} else {
|
||||
} elseif (!empty($origin)) {
|
||||
// Auto-allow domains with linked rule
|
||||
$rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin)));
|
||||
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
|
||||
$rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin)));
|
||||
} else {
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForPlatform->find('rules', [
|
||||
Query::equal('domain', [$origin]),
|
||||
Query::limit(1)
|
||||
])
|
||||
)[0] ?? new Document();
|
||||
}
|
||||
|
||||
if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getInternalId()) {
|
||||
$refDomainOrigin = $origin;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Create a new proxy rule.
|
||||
|
|
@ -5,6 +5,7 @@ namespace Appwrite\Platform;
|
|||
use Appwrite\Platform\Modules\Console;
|
||||
use Appwrite\Platform\Modules\Core;
|
||||
use Appwrite\Platform\Modules\Functions;
|
||||
use Appwrite\Platform\Modules\Proxy;
|
||||
use Appwrite\Platform\Modules\Sites;
|
||||
use Utopia\Platform\Platform;
|
||||
|
||||
|
|
@ -16,5 +17,6 @@ class Appwrite extends Platform
|
|||
$this->addModule(new Functions\Module());
|
||||
$this->addModule(new Sites\Module());
|
||||
$this->addModule(new Console\Module());
|
||||
$this->addModule(new Proxy\Module());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ use Appwrite\Event\Event;
|
|||
use Appwrite\Event\Validator\FunctionEvent;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Functions\Validator\RuntimeSpecification;
|
||||
use Appwrite\Messaging\Adapter\Realtime;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
|
|
@ -14,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse;
|
|||
use Appwrite\Task\Validator\Cron;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model\Rule;
|
||||
use Utopia\Abuse\Abuse;
|
||||
use Utopia\App;
|
||||
use Utopia\Config\Config;
|
||||
|
|
@ -229,72 +227,6 @@ class Create extends Base
|
|||
|
||||
$function = $dbForProject->updateDocument('functions', $function->getId(), $function);
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
if (!empty($functionsDomain)) {
|
||||
$routeSubdomain = ID::unique();
|
||||
$domain = "{$routeSubdomain}.{$functionsDomain}";
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique();
|
||||
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
'domain' => $domain,
|
||||
'resourceType' => 'function',
|
||||
'resourceId' => $function->getId(),
|
||||
'resourceInternalId' => $function->getInternalId(),
|
||||
'status' => 'verified',
|
||||
'certificateId' => '',
|
||||
]))
|
||||
);
|
||||
|
||||
/** Trigger Webhook */
|
||||
$ruleModel = new Rule();
|
||||
$ruleCreate =
|
||||
$queueForEvents
|
||||
->setClass(Event::WEBHOOK_CLASS_NAME)
|
||||
->setQueue(Event::WEBHOOK_QUEUE_NAME);
|
||||
|
||||
$ruleCreate
|
||||
->setProject($project)
|
||||
->setEvent('rules.[ruleId].create')
|
||||
->setParam('ruleId', $rule->getId())
|
||||
->setPayload($rule->getArrayCopy(array_keys($ruleModel->getRules())))
|
||||
->trigger();
|
||||
|
||||
/** Trigger Functions */
|
||||
$ruleCreate
|
||||
->setClass(Event::FUNCTIONS_CLASS_NAME)
|
||||
->setQueue(Event::FUNCTIONS_QUEUE_NAME)
|
||||
->trigger();
|
||||
|
||||
/** Trigger realtime event */
|
||||
$allEvents = Event::generateEvents('rules.[ruleId].create', [
|
||||
'ruleId' => $rule->getId(),
|
||||
]);
|
||||
$target = Realtime::fromPayload(
|
||||
// Pass first, most verbose event pattern
|
||||
event: $allEvents[0],
|
||||
payload: $rule,
|
||||
project: $project
|
||||
);
|
||||
Realtime::send(
|
||||
projectId: 'console',
|
||||
payload: $rule->getArrayCopy(),
|
||||
events: $allEvents,
|
||||
channels: $target['channels'],
|
||||
roles: $target['roles']
|
||||
);
|
||||
Realtime::send(
|
||||
projectId: $project->getId(),
|
||||
payload: $rule->getArrayCopy(),
|
||||
events: $allEvents,
|
||||
channels: $target['channels'],
|
||||
roles: $target['roles']
|
||||
);
|
||||
}
|
||||
|
||||
$queueForEvents->setParam('functionId', $function->getId());
|
||||
|
||||
$response
|
||||
|
|
|
|||
179
src/Appwrite/Platform/Modules/Proxy/Http/Rules/Create.php
Normal file
179
src/Appwrite/Platform/Modules/Proxy/Http/Rules/Create.php
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Proxy\Http\Rules;
|
||||
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\CNAME;
|
||||
use Appwrite\SDK\AuthType;
|
||||
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\Helpers\ID;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Domain as ValidatorDomain;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'createRule';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
|
||||
->setHttpPath('/v1/proxy/rules')
|
||||
->groups(['api', 'proxy'])
|
||||
->desc('Create rule')
|
||||
->label('scope', 'rules.write')
|
||||
->label('event', 'rules.[ruleId].create')
|
||||
->label('audits.event', 'rule.create')
|
||||
->label('audits.resource', 'rule/{response.$id}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'proxy',
|
||||
name: 'createRule',
|
||||
description: <<<EOT
|
||||
Create a new proxy rule.
|
||||
EOT,
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_CREATED,
|
||||
model: Response::MODEL_PROXY_RULE,
|
||||
)
|
||||
]
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'userId:{userId}, url:{url}')
|
||||
->label('abuse-time', 60)
|
||||
->param('domain', null, new ValidatorDomain(), 'Domain name.')
|
||||
->param('resourceType', null, new WhiteList(['api', 'function', 'site']), 'Action definition for the rule. Possible values are "api", "function" and "site"')
|
||||
->param('resourceId', '', new UID(), 'ID of resource for the action type. If resourceType is "api", leave empty. If resourceType is "function", provide ID of the function.', true)
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('queueForCertificates')
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForPlatform')
|
||||
->inject('dbForProject')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $domain, string $resourceType, string $resourceId, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject)
|
||||
{
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$deniedDomains = [
|
||||
$mainDomain,
|
||||
$sitesDomain,
|
||||
$functionsDomain,
|
||||
'localhost',
|
||||
APP_HOSTNAME_INTERNAL,
|
||||
];
|
||||
|
||||
if (in_array($domain, $deniedDomains, true)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.');
|
||||
}
|
||||
|
||||
$resourceInternalId = '';
|
||||
|
||||
switch ($resourceType) {
|
||||
case 'function':
|
||||
case 'site':
|
||||
if (empty($resourceId)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'resourceId cannot be empty for resourceType "' . $resourceType . '".');
|
||||
}
|
||||
|
||||
$expectedDomain = ($resourceType === 'function') ? $functionsDomain : $sitesDomain;
|
||||
if (!\str_ends_with($domain, $expectedDomain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain must end with ' . $expectedDomain . ' for resourceType "' . $resourceType . '".');
|
||||
}
|
||||
|
||||
$collection = ($resourceType === 'function') ? 'functions' : 'sites';
|
||||
$document = $dbForProject->getDocument($collection, $resourceId);
|
||||
|
||||
if ($document->isEmpty()) {
|
||||
throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$resourceInternalId = $document->getInternalId();
|
||||
break;
|
||||
case 'api':
|
||||
if (\str_ends_with($domain, $functionsDomain) || \str_ends_with($domain, $sitesDomain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain must not end with ' . $functionsDomain . ' or ' . $sitesDomain . ' for resourceType "api".');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
$domain = new Domain($domain);
|
||||
} catch (\Throwable) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.');
|
||||
}
|
||||
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
||||
|
||||
try {
|
||||
$rule = new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
'domain' => $domain->get(),
|
||||
'resourceType' => $resourceType,
|
||||
'resourceId' => $resourceId,
|
||||
'resourceInternalId' => $resourceInternalId,
|
||||
'certificateId' => '',
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
if ($e->getCode() === Exception::DOCUMENT_ALREADY_EXISTS) {
|
||||
throw new Exception(Exception::RULE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'An unexpected error occurred: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$status = 'created';
|
||||
|
||||
if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) {
|
||||
$status = 'verified';
|
||||
}
|
||||
|
||||
if ($status === 'created') {
|
||||
$target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
$validator = new CNAME($target->get()); // Verify Domain with DNS records
|
||||
|
||||
if ($validator->isValid($domain->get())) {
|
||||
$status = 'verifying';
|
||||
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain')
|
||||
]))
|
||||
->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
$rule->setAttribute('status', $status);
|
||||
$rule = $dbForPlatform->createDocument('rules', $rule);
|
||||
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
}
|
||||
}
|
||||
14
src/Appwrite/Platform/Modules/Proxy/Module.php
Normal file
14
src/Appwrite/Platform/Modules/Proxy/Module.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Proxy;
|
||||
|
||||
use Appwrite\Platform\Modules\Proxy\Services\Http;
|
||||
use Utopia\Platform;
|
||||
|
||||
class Module extends Platform\Module
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->addService('http', new Http());
|
||||
}
|
||||
}
|
||||
16
src/Appwrite/Platform/Modules/Proxy/Services/Http.php
Normal file
16
src/Appwrite/Platform/Modules/Proxy/Services/Http.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Proxy\Services;
|
||||
|
||||
use Appwrite\Platform\Modules\Proxy\Http\Rules\Create as CreateRule;
|
||||
use Utopia\Platform\Service;
|
||||
|
||||
class Http extends Service
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->type = Service::TYPE_HTTP;
|
||||
// Rules
|
||||
$this->addAction(CreateRule::getName(), new CreateRule());
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ namespace Appwrite\Platform\Modules\Sites\Http\Sites;
|
|||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Messaging\Adapter\Realtime;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
|
|
@ -12,7 +11,6 @@ use Appwrite\SDK\Response as SDKResponse;
|
|||
use Appwrite\Sites\Validator\FrameworkSpecification;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model\Rule;
|
||||
use Utopia\App;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
|
|
@ -20,7 +18,6 @@ use Utopia\Database\Document;
|
|||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
|
|
@ -71,7 +68,6 @@ class Create extends Base
|
|||
->param('installCommand', '', new Text(8192, 0), 'Install Command.', true)
|
||||
->param('buildCommand', '', new Text(8192, 0), 'Build Command.', true)
|
||||
->param('outputDirectory', '', new Text(8192, 0), 'Output Directory for site.', true)
|
||||
->param('subdomain', '', new CustomId(), 'Unique custom sub-domain. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true)
|
||||
->param('buildRuntime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Runtime to use during build step.')
|
||||
->param('adapter', '', new Text(8192, 0), 'Framework adapter. Allows: static, ssr', true)
|
||||
->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Control System) deployment.', true)
|
||||
|
|
@ -94,7 +90,7 @@ class Create extends Base
|
|||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $subdomain, string $buildRuntime, string $adapter, string $installationId, ?string $fallbackFile, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Database $dbForPlatform)
|
||||
public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $buildRuntime, string $adapter, string $installationId, ?string $fallbackFile, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Database $dbForPlatform)
|
||||
{
|
||||
if (!empty($adapter)) {
|
||||
$configFramework = Config::getParam('frameworks')[$framework] ?? [];
|
||||
|
|
@ -105,21 +101,6 @@ class Create extends Base
|
|||
}
|
||||
}
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$routeSubdomain = '';
|
||||
$domain = '';
|
||||
|
||||
if (!empty($sitesDomain)) {
|
||||
$routeSubdomain = $subdomain ?: ID::unique();
|
||||
$domain = "{$routeSubdomain}.{$sitesDomain}";
|
||||
|
||||
$subdomain = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', \md5($domain)));
|
||||
|
||||
if ($subdomain && !$subdomain->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Subdomain already exists. Please choose a different subdomain.');
|
||||
}
|
||||
}
|
||||
|
||||
$siteId = ($siteId == 'unique()') ? ID::unique() : $siteId;
|
||||
|
||||
$allowList = \array_filter(\explode(',', System::getEnv('_APP_SITES_FRAMEWORKS', '')));
|
||||
|
|
@ -195,67 +176,6 @@ class Create extends Base
|
|||
|
||||
$site = $dbForProject->updateDocument('sites', $site->getId(), $site);
|
||||
|
||||
if (!empty($sitesDomain)) {
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => \md5($domain),
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
'domain' => $domain,
|
||||
'resourceType' => 'site',
|
||||
'resourceId' => $site->getId(),
|
||||
'resourceInternalId' => $site->getInternalId(),
|
||||
'status' => 'verified',
|
||||
'certificateId' => '',
|
||||
]))
|
||||
);
|
||||
|
||||
/** Trigger Webhook */
|
||||
$ruleModel = new Rule();
|
||||
$ruleCreate =
|
||||
$queueForEvents
|
||||
->setClass(Event::WEBHOOK_CLASS_NAME)
|
||||
->setQueue(Event::WEBHOOK_QUEUE_NAME);
|
||||
|
||||
$ruleCreate
|
||||
->setProject($project)
|
||||
->setEvent('rules.[ruleId].create')
|
||||
->setParam('ruleId', $rule->getId())
|
||||
->setPayload($rule->getArrayCopy(array_keys($ruleModel->getRules())))
|
||||
->trigger();
|
||||
|
||||
/** Trigger Sites */
|
||||
$ruleCreate
|
||||
->setClass(Event::SITES_CLASS_NAME)
|
||||
->setQueue(Event::SITES_QUEUE_NAME)
|
||||
->trigger();
|
||||
|
||||
/** Trigger realtime event */
|
||||
$allEvents = Event::generateEvents('rules.[ruleId].create', [
|
||||
'ruleId' => $rule->getId(),
|
||||
]);
|
||||
$target = Realtime::fromPayload(
|
||||
// Pass first, most verbose event pattern
|
||||
event: $allEvents[0],
|
||||
payload: $rule,
|
||||
project: $project
|
||||
);
|
||||
Realtime::send(
|
||||
projectId: 'console',
|
||||
payload: $rule->getArrayCopy(),
|
||||
events: $allEvents,
|
||||
channels: $target['channels'],
|
||||
roles: $target['roles']
|
||||
);
|
||||
Realtime::send(
|
||||
projectId: $project->getId(),
|
||||
payload: $rule->getArrayCopy(),
|
||||
events: $allEvents,
|
||||
channels: $target['channels'],
|
||||
roles: $target['roles']
|
||||
);
|
||||
}
|
||||
|
||||
$queueForEvents->setParam('siteId', $site->getId());
|
||||
|
||||
$response
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@ use Tests\E2E\Scopes\ProjectCustom;
|
|||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideServer;
|
||||
use Tests\E2E\Services\Functions\FunctionsBase;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\System\System;
|
||||
|
||||
class UsageTest extends Scope
|
||||
{
|
||||
|
|
@ -1090,22 +1092,25 @@ class UsageTest extends Scope
|
|||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
$rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::equal('resourceId', [$functionId])->toString(),
|
||||
Query::equal('resourceType', ['function'])->toString(),
|
||||
$rule = $this->client->call(
|
||||
Client::METHOD_POST,
|
||||
'/proxy/rules',
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()),
|
||||
[
|
||||
'domain' => 'test-' . ID::unique() . System::getEnv('_APP_DOMAIN_FUNCTIONS'),
|
||||
'resourceType' => 'function',
|
||||
'resourceId' => $functionId,
|
||||
],
|
||||
]);
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
$this->assertEquals(1, $rules['body']['total']);
|
||||
$this->assertCount(1, $rules['body']['rules']);
|
||||
$this->assertNotEmpty($rules['body']['rules'][0]['domain']);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertNotEmpty($rule['body']['$id']);
|
||||
$this->assertNotEmpty($rule['body']['domain']);
|
||||
|
||||
$domain = $rules['body']['rules'][0]['domain'];
|
||||
$domain = $rule['body']['domain'];
|
||||
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ use Appwrite\Tests\Async;
|
|||
use CURLFile;
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\System\System;
|
||||
|
||||
trait FunctionsBase
|
||||
{
|
||||
|
|
@ -255,4 +258,47 @@ trait FunctionsBase
|
|||
|
||||
return $function;
|
||||
}
|
||||
|
||||
protected function setupFunctionDomain(string $functionId, string $subdomain = ''): string
|
||||
{
|
||||
$subdomain = $subdomain ? $subdomain : ID::unique();
|
||||
$rule = $this->client->call(Client::METHOD_POST, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_FUNCTIONS', ''),
|
||||
'resourceType' => 'function',
|
||||
'resourceId' => $functionId,
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertNotEmpty($rule['body']['$id']);
|
||||
$this->assertNotEmpty($rule['body']['domain']);
|
||||
|
||||
$domain = $rule['body']['domain'];
|
||||
|
||||
return $domain;
|
||||
}
|
||||
|
||||
protected function getFunctionDomain(string $functionId): string
|
||||
{
|
||||
$rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::equal('resourceId', [$functionId])->toString(),
|
||||
Query::equal('resourceType', ['function'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
$this->assertGreaterThanOrEqual(1, $rules['body']['total']);
|
||||
$this->assertGreaterThanOrEqual(1, \count($rules['body']['rules']));
|
||||
$this->assertNotEmpty($rules['body']['rules'][0]['domain']);
|
||||
|
||||
$domain = $rules['body']['rules'][0]['domain'];
|
||||
|
||||
return $domain;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1654,22 +1654,7 @@ class FunctionsCustomServerTest extends Scope
|
|||
'execute' => ['any']
|
||||
]);
|
||||
|
||||
$rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::equal('resourceId', [$functionId])->toString(),
|
||||
Query::equal('resourceType', ['function'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
$this->assertEquals(1, $rules['body']['total']);
|
||||
$this->assertCount(1, $rules['body']['rules']);
|
||||
$this->assertNotEmpty($rules['body']['rules'][0]['domain']);
|
||||
|
||||
$domain = $rules['body']['rules'][0]['domain'];
|
||||
$domain = $this->setupFunctionDomain($functionId);
|
||||
|
||||
$this->setupDeployment($functionId, [
|
||||
'entrypoint' => 'index.php',
|
||||
|
|
@ -1730,22 +1715,7 @@ class FunctionsCustomServerTest extends Scope
|
|||
'execute' => ['any']
|
||||
]);
|
||||
|
||||
$rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::equal('resourceId', [$functionId])->toString(),
|
||||
Query::equal('resourceType', ['function'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
$this->assertEquals(1, $rules['body']['total']);
|
||||
$this->assertCount(1, $rules['body']['rules']);
|
||||
$this->assertNotEmpty($rules['body']['rules'][0]['domain']);
|
||||
|
||||
$domain = $rules['body']['rules'][0]['domain'];
|
||||
$domain = $this->setupFunctionDomain($functionId);
|
||||
|
||||
$this->setupDeployment($functionId, [
|
||||
'entrypoint' => 'index.php',
|
||||
|
|
@ -1780,22 +1750,7 @@ class FunctionsCustomServerTest extends Scope
|
|||
'execute' => ['any']
|
||||
]);
|
||||
|
||||
$rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::equal('resourceId', [$functionId])->toString(),
|
||||
Query::equal('resourceType', ['function'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
$this->assertEquals(1, $rules['body']['total']);
|
||||
$this->assertCount(1, $rules['body']['rules']);
|
||||
$this->assertNotEmpty($rules['body']['rules'][0]['domain']);
|
||||
|
||||
$domain = $rules['body']['rules'][0]['domain'];
|
||||
$domain = $this->setupFunctionDomain($functionId);
|
||||
|
||||
$this->setupDeployment($functionId, [
|
||||
'entrypoint' => 'index.php',
|
||||
|
|
@ -1915,6 +1870,8 @@ class FunctionsCustomServerTest extends Scope
|
|||
|
||||
$functionId = $function['body']['$id'] ?? '';
|
||||
|
||||
$domain = $this->setupFunctionDomain($functionId);
|
||||
|
||||
$this->setupDeployment($functionId, [
|
||||
'code' => $this->packageFunction('node'),
|
||||
'activate' => true
|
||||
|
|
@ -1949,20 +1906,7 @@ class FunctionsCustomServerTest extends Scope
|
|||
}, 10000, 500);
|
||||
|
||||
// Domain Executions test
|
||||
$rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::equal('resourceId', [$functionId])->toString(),
|
||||
Query::equal('resourceType', ['function'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
$this->assertNotEmpty($rules['body']['rules'][0]['domain']);
|
||||
|
||||
$domain = $rules['body']['rules'][0]['domain'];
|
||||
$domain = $this->getFunctionDomain($functionId);
|
||||
|
||||
$proxyClient = new Client();
|
||||
$proxyClient->setEndpoint('http://' . $domain);
|
||||
|
|
|
|||
|
|
@ -31,11 +31,25 @@ class ProjectsCustomServerTest extends Scope
|
|||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [
|
||||
'resourceType' => 'api',
|
||||
'domain' => 'abc.test.io',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
// duplicate rule
|
||||
$response2 = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [
|
||||
'resourceType' => 'api',
|
||||
'domain' => 'abc.test.io',
|
||||
]);
|
||||
|
||||
$this->assertEquals(409, $response2['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/proxy/rules/' . $response['body']['$id'], $headers);
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
// prevent functions domain
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [
|
||||
|
|
@ -45,7 +59,7 @@ class ProjectsCustomServerTest extends Scope
|
|||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// prevent sites domain
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [
|
||||
|
|
@ -54,5 +68,42 @@ class ProjectsCustomServerTest extends Scope
|
|||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// prevent functions domain
|
||||
$response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [
|
||||
'resourceType' => 'function',
|
||||
'domain' => $functionsDomain,
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// prevent sites domain
|
||||
$response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [
|
||||
'resourceType' => 'site',
|
||||
'domain' => $sitesDomain,
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$deniedDomains = [
|
||||
$mainDomain,
|
||||
$sitesDomain,
|
||||
$functionsDomain,
|
||||
'localhost',
|
||||
APP_HOSTNAME_INTERNAL,
|
||||
];
|
||||
|
||||
foreach ($deniedDomains as $deniedDomain) {
|
||||
$response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [
|
||||
'resourceType' => 'api',
|
||||
'domain' => $deniedDomain,
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ use Appwrite\Tests\Async;
|
|||
use CURLFile;
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\System\System;
|
||||
|
||||
trait SitesBase
|
||||
{
|
||||
|
|
@ -267,6 +269,27 @@ trait SitesBase
|
|||
return $site;
|
||||
}
|
||||
|
||||
protected function setupSiteDomain(string $siteId, string $subdomain = ''): string
|
||||
{
|
||||
$subdomain = $subdomain ? $subdomain : ID::unique();
|
||||
$rule = $this->client->call(Client::METHOD_POST, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
'resourceType' => 'site',
|
||||
'resourceId' => $siteId,
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertNotEmpty($rule['body']['$id']);
|
||||
$this->assertNotEmpty($rule['body']['domain']);
|
||||
|
||||
$domain = $rule['body']['domain'];
|
||||
|
||||
return $domain;
|
||||
}
|
||||
|
||||
protected function getSiteDomain(string $siteId): string
|
||||
{
|
||||
$rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use Utopia\Database\Document;
|
|||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\System\System;
|
||||
|
||||
class SitesCustomServerTest extends Scope
|
||||
{
|
||||
|
|
@ -73,13 +74,12 @@ class SitesCustomServerTest extends Scope
|
|||
'framework' => 'other',
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'outputDirectory' => './',
|
||||
'subdomain' => 'test-site',
|
||||
'fallbackFile' => null,
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($siteId);
|
||||
|
||||
$rule = $this->getSiteDomain($siteId);
|
||||
$rule = $this->setupSiteDomain($siteId);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/console/resources', [
|
||||
'origin' => 'http://localhost',
|
||||
|
|
@ -289,6 +289,8 @@ class SitesCustomServerTest extends Scope
|
|||
|
||||
$this->assertNotEmpty($siteId);
|
||||
|
||||
$domain = $this->setupSiteDomain($siteId);
|
||||
|
||||
$secretVariable = $this->createVariable($siteId, [
|
||||
'key' => 'name',
|
||||
'value' => 'Appwrite',
|
||||
|
|
@ -1243,7 +1245,7 @@ class SitesCustomServerTest extends Scope
|
|||
$this->assertNotEmpty($site['body']['deploymentId']);
|
||||
}, 50000, 500);
|
||||
|
||||
$domain = $this->getSiteDomain($siteId);
|
||||
$domain = $this->setupSiteDomain($siteId);
|
||||
$proxyClient = new Client();
|
||||
$proxyClient->setEndpoint('http://' . $domain);
|
||||
|
||||
|
|
@ -1270,8 +1272,6 @@ class SitesCustomServerTest extends Scope
|
|||
|
||||
public function testSiteDomainReclaiming(): void
|
||||
{
|
||||
$subdomain = 'startup' . \uniqid();
|
||||
|
||||
$siteId = $this->setupSite([
|
||||
'siteId' => ID::unique(),
|
||||
'name' => 'Startup site',
|
||||
|
|
@ -1282,11 +1282,13 @@ class SitesCustomServerTest extends Scope
|
|||
'buildCommand' => '',
|
||||
'installCommand' => '',
|
||||
'fallbackFile' => '',
|
||||
'subdomain' => $subdomain
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($siteId);
|
||||
|
||||
$subdomain = 'startup' . \uniqid();
|
||||
$domain = $this->setupSiteDomain($siteId, $subdomain);
|
||||
|
||||
$deploymentId = $this->setupDeployment($siteId, [
|
||||
'code' => $this->packageSite('static'),
|
||||
'activate' => 'true'
|
||||
|
|
@ -1306,7 +1308,7 @@ class SitesCustomServerTest extends Scope
|
|||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertStringNotContainsString("This domain is not connected to any Appwrite resource yet", $response['body']);
|
||||
|
||||
$site = $this->createSite([
|
||||
$site2 = $this->createSite([
|
||||
'siteId' => ID::unique(),
|
||||
'name' => 'Startup 2 site',
|
||||
'framework' => 'other',
|
||||
|
|
@ -1316,11 +1318,21 @@ class SitesCustomServerTest extends Scope
|
|||
'buildCommand' => '',
|
||||
'installCommand' => '',
|
||||
'fallbackFile' => '',
|
||||
'subdomain' => $subdomain
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $site['headers']['status-code']);
|
||||
$this->assertStringContainsString("Subdomain already exists.", $site['body']['message']);
|
||||
$siteId2 = $site2['body']['$id'];
|
||||
|
||||
$rule = $this->client->call(Client::METHOD_POST, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
'resourceType' => 'site',
|
||||
'resourceId' => $siteId2,
|
||||
]);
|
||||
|
||||
$this->assertEquals(409, $rule['headers']['status-code']);
|
||||
$this->assertStringContainsString("Document with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.", $rule['body']['message']);
|
||||
|
||||
$this->cleanupSite($siteId);
|
||||
|
||||
|
|
@ -1356,10 +1368,16 @@ class SitesCustomServerTest extends Scope
|
|||
'buildCommand' => '',
|
||||
'installCommand' => '',
|
||||
'fallbackFile' => '',
|
||||
'subdomain' => $subdomain
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $site['headers']['status-code']);
|
||||
$this->assertNotEmpty($site['body']['$id']);
|
||||
|
||||
$siteId = $site['body']['$id'];
|
||||
|
||||
$domain = $this->setupSiteDomain($siteId, $subdomain);
|
||||
|
||||
$this->assertNotEmpty($domain);
|
||||
|
||||
$this->cleanupSite($site['body']['$id']);
|
||||
}
|
||||
|
|
@ -1380,6 +1398,8 @@ class SitesCustomServerTest extends Scope
|
|||
|
||||
$this->assertNotEmpty($siteId);
|
||||
|
||||
$domain = $this->setupSiteDomain($siteId);
|
||||
|
||||
$deploymentId = $this->setupDeployment($siteId, [
|
||||
'code' => $this->packageSite('static'),
|
||||
'activate' => 'true'
|
||||
|
|
@ -1443,6 +1463,7 @@ class SitesCustomServerTest extends Scope
|
|||
|
||||
$this->assertNotEmpty($siteId);
|
||||
|
||||
$this->setupSiteDomain($siteId, $subdomain);
|
||||
$domain = $this->getSiteDomain($siteId);
|
||||
|
||||
$this->assertNotEmpty($domain);
|
||||
|
|
|
|||
Loading…
Reference in a new issue