mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Compare commits
79
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe15741217 | ||
|
|
606b666aed | ||
|
|
1413a66f0a | ||
|
|
2262494f87 | ||
|
|
c66a6a14b4 | ||
|
|
a233c3b82f | ||
|
|
1e28f0b2fb | ||
|
|
a5f44aebc3 | ||
|
|
ea15cafc34 | ||
|
|
9cc152d173 | ||
|
|
c8d069f35e | ||
|
|
6ce46e29d0 | ||
|
|
4962a1d7e0 | ||
|
|
eed36f36bf | ||
|
|
790c440799 | ||
|
|
ac42bb04f4 | ||
|
|
0b83b5b22b | ||
|
|
80397374bc | ||
|
|
8ce47393e8 | ||
|
|
2d10819875 | ||
|
|
6335363853 | ||
|
|
9c8202df52 | ||
|
|
d9d6270a15 | ||
|
|
ae6e608e25 | ||
|
|
293d52715e | ||
|
|
eeb163b1c7 | ||
|
|
1c2819fcad | ||
|
|
6615375b3b | ||
|
|
37ddaa78c9 | ||
|
|
4b16da92d8 | ||
|
|
6589efa87f | ||
|
|
d81beb9c99 | ||
|
|
779fb01b96 | ||
|
|
3313d78fad | ||
|
|
2b09805957 | ||
|
|
dbae081225 | ||
|
|
1ac35054fe | ||
|
|
ad795b4fd1 | ||
|
|
47cf9aa0fc | ||
|
|
0af3338cab | ||
|
|
00fb346b7a | ||
|
|
daacc4d437 | ||
|
|
04adfd1e04 | ||
|
|
db80b74f1f | ||
|
|
3f46b06634 | ||
|
|
91bac63dbd | ||
|
|
e93b06acb5 | ||
|
|
4a3a74d284 | ||
|
|
7b46197ffe | ||
|
|
824d90edc0 | ||
|
|
e6de282275 | ||
|
|
616fef17a8 | ||
|
|
448dd9696c | ||
|
|
9fe68dbdde | ||
|
|
8b38dc7326 | ||
|
|
83811c0c33 | ||
|
|
6463892ba9 | ||
|
|
636ce72e52 | ||
|
|
db664318c4 | ||
|
|
cf0838d75b | ||
|
|
e508f049bf | ||
|
|
cfbb6d9453 | ||
|
|
72e936a004 | ||
|
|
613065b074 | ||
|
|
0d594de9d7 | ||
|
|
3eb1d74ba9 | ||
|
|
7d7e866ddf | ||
|
|
3e905f9d6b | ||
|
|
b4a49107f1 | ||
|
|
4c4892a214 | ||
|
|
951baa1392 | ||
|
|
921c0344a0 | ||
|
|
cdb400b538 | ||
|
|
039a2361b4 | ||
|
|
c2faf18da6 | ||
|
|
b391c2ac74 | ||
|
|
64fe298f91 | ||
|
|
c81b2ebcae | ||
|
|
60dd501793 |
@@ -21,13 +21,13 @@ _APP_OPTIONS_ROUTER_PROTECTION=disabled
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||
_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled
|
||||
_APP_OPENSSL_KEY_V1=your-secret-key
|
||||
_APP_DNS=8.8.8.8
|
||||
_APP_DNS=172.16.238.100 # CoreDNS
|
||||
_APP_DOMAIN=traefik
|
||||
_APP_CONSOLE_DOMAIN=localhost
|
||||
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
||||
_APP_DOMAIN_SITES=sites.localhost
|
||||
_APP_DOMAIN_TARGET_CNAME=test.localhost
|
||||
_APP_DOMAIN_TARGET_A=127.0.0.1
|
||||
_APP_DOMAIN_TARGET_CNAME=cname.localhost
|
||||
_APP_DOMAIN_TARGET_A=203.0.0.1
|
||||
_APP_DOMAIN_TARGET_AAAA=::1
|
||||
_APP_DOMAIN_TARGET_CAA=digicert.com
|
||||
_APP_RULES_FORMAT=md5
|
||||
|
||||
@@ -1185,6 +1185,17 @@ return [
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('logs'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 65535,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('redirectStatusCode'),
|
||||
'type' => Database::VAR_INTEGER,
|
||||
|
||||
@@ -59174,13 +59174,12 @@
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Domain verification status. Possible values are \"created\", \"verifying\", \"verified\" and \"unverified\"",
|
||||
"x-example": "verified",
|
||||
"enum": [
|
||||
"created",
|
||||
"verifying",
|
||||
"verified",
|
||||
"unverified"
|
||||
]
|
||||
"x-example": "verified"
|
||||
},
|
||||
"verificationLogs": {
|
||||
"type": "string",
|
||||
"description": "DNS verification logs. This contains error from last verification attempt.",
|
||||
"x-example": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record."
|
||||
},
|
||||
"logs": {
|
||||
"type": "string",
|
||||
@@ -59207,6 +59206,7 @@
|
||||
"deploymentResourceId",
|
||||
"deploymentVcsProviderBranch",
|
||||
"status",
|
||||
"verificationLogs",
|
||||
"logs",
|
||||
"renewAt"
|
||||
],
|
||||
@@ -59224,6 +59224,7 @@
|
||||
"deploymentResourceId": "n3u9feiwmf",
|
||||
"deploymentVcsProviderBranch": "main",
|
||||
"status": "verified",
|
||||
"verificationLogs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.",
|
||||
"logs": "HTTP challegne failed.",
|
||||
"renewAt": "datetime"
|
||||
}
|
||||
|
||||
@@ -59105,13 +59105,12 @@
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Domain verification status. Possible values are \"created\", \"verifying\", \"verified\" and \"unverified\"",
|
||||
"x-example": "verified",
|
||||
"enum": [
|
||||
"created",
|
||||
"verifying",
|
||||
"verified",
|
||||
"unverified"
|
||||
]
|
||||
"x-example": "verified"
|
||||
},
|
||||
"verificationLogs": {
|
||||
"type": "string",
|
||||
"description": "DNS verification logs. This contains error from last verification attempt.",
|
||||
"x-example": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record."
|
||||
},
|
||||
"logs": {
|
||||
"type": "string",
|
||||
@@ -59138,6 +59137,7 @@
|
||||
"deploymentResourceId",
|
||||
"deploymentVcsProviderBranch",
|
||||
"status",
|
||||
"verificationLogs",
|
||||
"logs",
|
||||
"renewAt"
|
||||
],
|
||||
@@ -59155,6 +59155,7 @@
|
||||
"deploymentResourceId": "n3u9feiwmf",
|
||||
"deploymentVcsProviderBranch": "main",
|
||||
"status": "verified",
|
||||
"verificationLogs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.",
|
||||
"logs": "HTTP challegne failed.",
|
||||
"renewAt": "datetime"
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
'deploymentResourceId' => $resourceId,
|
||||
'deploymentResourceInternalId' => $resourceInternalId,
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
@@ -389,7 +389,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
'deploymentResourceId' => $resourceId,
|
||||
'deploymentResourceInternalId' => $resourceInternalId,
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
@@ -420,7 +420,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
'deploymentResourceId' => $resourceId,
|
||||
'deploymentResourceInternalId' => $resourceInternalId,
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
|
||||
@@ -973,7 +973,7 @@ App::init()
|
||||
'$id' => $ruleId,
|
||||
'domain' => $domain->get(),
|
||||
'type' => 'api',
|
||||
'status' => 'verifying',
|
||||
'status' => RULE_STATUS_GENERATING_CERTIFICATE,
|
||||
'projectId' => $console->getId(),
|
||||
'projectInternalId' => $console->getSequence(),
|
||||
'search' => implode(' ', [$ruleId, $domain->get()]),
|
||||
|
||||
@@ -140,7 +140,11 @@ const DELETE_TYPE_EXPIRED_TARGETS = 'invalid_targets';
|
||||
const DELETE_TYPE_SESSION_TARGETS = 'session_targets';
|
||||
const DELETE_TYPE_CSV_EXPORTS = 'csv_exports';
|
||||
const DELETE_TYPE_MAINTENANCE = 'maintenance';
|
||||
|
||||
// Rule types
|
||||
const RULE_STATUS_VERIFICATION_FAILED = 'created';
|
||||
const RULE_STATUS_GENERATING_CERTIFICATE = 'verifying';
|
||||
const RULE_STATUS_GENERATION_FAILED = 'unverified';
|
||||
const RULE_STATUS_SUCCESSFUL = 'verified';
|
||||
// Message types
|
||||
const MESSAGE_SEND_TYPE_INTERNAL = 'internal';
|
||||
const MESSAGE_SEND_TYPE_EXTERNAL = 'external';
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@
|
||||
"utopia-php/detector": "0.2.*",
|
||||
"utopia-php/domains": "0.9.*",
|
||||
"utopia-php/emails": "0.6.*",
|
||||
"utopia-php/dns": "1.1.*",
|
||||
"utopia-php/dns": "1.3.*",
|
||||
"utopia-php/dsn": "0.2.1",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/fetch": "0.4.*",
|
||||
|
||||
Generated
+9
-9
@@ -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": "dc4eb1888275a24d596468924e272e25",
|
||||
"content-hash": "98b10a56d6dc9787512620f14b3c22a0",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
@@ -3943,16 +3943,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/dns",
|
||||
"version": "1.1.3",
|
||||
"version": "1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/dns.git",
|
||||
"reference": "1e6b4bac735329c9e5ec69a6a5d899ec2d050707"
|
||||
"reference": "7644276913f68648515228d68684feca8742a645"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/1e6b4bac735329c9e5ec69a6a5d899ec2d050707",
|
||||
"reference": "1e6b4bac735329c9e5ec69a6a5d899ec2d050707",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/7644276913f68648515228d68684feca8742a645",
|
||||
"reference": "7644276913f68648515228d68684feca8742a645",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3994,9 +3994,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/dns/issues",
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.1.3"
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.3.0"
|
||||
},
|
||||
"time": "2025-11-06T19:08:29+00:00"
|
||||
"time": "2025-11-12T19:24:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
@@ -8893,7 +8893,7 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
@@ -8917,5 +8917,5 @@
|
||||
"platform-overrides": {
|
||||
"php": "8.3"
|
||||
},
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
||||
@@ -89,9 +89,12 @@ services:
|
||||
- ./public:/usr/src/code/public
|
||||
- ./src:/usr/src/code/src
|
||||
- ./dev:/usr/src/code/dev
|
||||
dns:
|
||||
- 172.16.238.100
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
- coredns
|
||||
# - clamav
|
||||
entrypoint:
|
||||
- php
|
||||
@@ -524,9 +527,12 @@ services:
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
dns:
|
||||
- 172.16.238.100
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- coredns
|
||||
volumes:
|
||||
- appwrite-config:/storage/config:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
@@ -1069,6 +1075,21 @@ services:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-redis:/data:rw
|
||||
|
||||
coredns: # DNS server for testing purposes (Proxy APIs)
|
||||
image: coredns/coredns:1.12.4
|
||||
container_name: appwrite-coredns
|
||||
restart: unless-stopped
|
||||
<<: *x-logging
|
||||
command: ["-conf", "/mnt/resources/Corefile"]
|
||||
# If you need to debug CoreDNS, do it from "appwrite container", or port forward:
|
||||
# ports:
|
||||
# - "53:53"
|
||||
networks:
|
||||
appwrite:
|
||||
ipv4_address: 172.16.238.100
|
||||
volumes:
|
||||
- ./tests/resources/coredns:/mnt/resources:ro
|
||||
|
||||
# Dev Tools Start ------------------------------------------------------------------------------------------
|
||||
#
|
||||
@@ -1147,6 +1168,9 @@ networks:
|
||||
name: gateway
|
||||
appwrite:
|
||||
name: appwrite
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.16.238.0/24
|
||||
runtimes:
|
||||
name: runtimes
|
||||
|
||||
|
||||
@@ -6,9 +6,13 @@ use Utopia\Logger\Log;
|
||||
|
||||
interface Adapter
|
||||
{
|
||||
public function isIssueInstant(string $domain, ?string $domainType): bool;
|
||||
|
||||
public function issueCertificate(string $certName, string $domain, ?string $domainType): ?string;
|
||||
|
||||
public function isRenewRequired(string $domain, ?string $domainType, Log $log): bool;
|
||||
|
||||
public function deleteCertificate(string $domain): void;
|
||||
|
||||
public function getIssueStatus(string $domain, ?string $domainType): ?string;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Certificates\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
// Exception thrown during certificate issue status checking
|
||||
//
|
||||
class IssueStatus extends Exception
|
||||
{
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Appwrite\Certificates;
|
||||
|
||||
use Appwrite\Certificates\Exceptions\IssueStatus as IssueStatusException;
|
||||
use Exception;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
@@ -17,6 +18,15 @@ class LetsEncrypt implements Adapter
|
||||
$this->email = $email;
|
||||
}
|
||||
|
||||
public function isIssueInstant(string $domain, ?string $domainType): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getIssueStatus(string $domain, ?string $domainType): ?string
|
||||
{
|
||||
throw new IssueStatusException('Issue status synchronization is not supported in this adapter.');
|
||||
}
|
||||
|
||||
public function issueCertificate(string $certName, string $domain, ?string $domainType): ?string
|
||||
{
|
||||
|
||||
@@ -7,9 +7,14 @@ use Utopia\Queue\Publisher;
|
||||
|
||||
class Certificate extends Event
|
||||
{
|
||||
public const ACTION_VERIFICATION = 'verification';
|
||||
public const ACTION_GENERATION = 'generation';
|
||||
|
||||
protected bool $skipRenewCheck = false;
|
||||
protected ?Document $domain = null;
|
||||
protected ?string $validationDomain = null;
|
||||
protected ?string $verificationDomainFunction = null; // For example: fra.cloud.appwrite.io
|
||||
protected ?string $verificationDomainAPI = null; // For example: fra.appwrite.run
|
||||
protected string $action = self::ACTION_GENERATION;
|
||||
|
||||
public function __construct(protected Publisher $publisher)
|
||||
{
|
||||
@@ -58,26 +63,49 @@ class Certificate extends Event
|
||||
|
||||
|
||||
/**
|
||||
* Set override for main domain used for validation
|
||||
* Set verification domain function.
|
||||
*
|
||||
* @param string|null $validationDomain
|
||||
* @param ?string $verificationDomainFunction
|
||||
* @return self
|
||||
*/
|
||||
public function setValidationDomain(?string $validationDomain): self
|
||||
public function setVerificationDomainFunction(?string $verificationDomainFunction): self
|
||||
{
|
||||
$this->validationDomain = $validationDomain;
|
||||
$this->verificationDomainFunction = $verificationDomainFunction;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get validation domain
|
||||
* Get verification domain function.
|
||||
*
|
||||
* @return string|null
|
||||
* @return ?string
|
||||
*/
|
||||
public function getValidationDomain(): ?string
|
||||
public function getVerificationDomainFunction(): ?string
|
||||
{
|
||||
return $this->validationDomain;
|
||||
return $this->verificationDomainFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set verification domain api.
|
||||
*
|
||||
* @param ?string $verificationDomainAPI
|
||||
* @return self
|
||||
*/
|
||||
public function setVerificationDomainAPI(?string $verificationDomainAPI): self
|
||||
{
|
||||
$this->verificationDomainAPI = $verificationDomainAPI;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get verification domain api.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getVerificationDomainAPI(): ?string
|
||||
{
|
||||
return $this->verificationDomainAPI;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,6 +118,28 @@ class Certificate extends Event
|
||||
return $this->skipRenewCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set action for this certificate event.
|
||||
*
|
||||
* @param string $action
|
||||
* @return self
|
||||
*/
|
||||
public function setAction(string $action): self
|
||||
{
|
||||
$this->action = $action;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get action for this certificate event.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAction(): string
|
||||
{
|
||||
return $this->action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the payload for the event
|
||||
@@ -102,7 +152,9 @@ class Certificate extends Event
|
||||
'project' => $this->project,
|
||||
'domain' => $this->domain,
|
||||
'skipRenewCheck' => $this->skipRenewCheck,
|
||||
'validationDomain' => $this->validationDomain
|
||||
'verificationDomainFunction' => $this->verificationDomainFunction,
|
||||
'verificationDomainAPI' => $this->verificationDomainAPI,
|
||||
'action' => $this->action
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,115 +2,69 @@
|
||||
|
||||
namespace Appwrite\Network\Validator;
|
||||
|
||||
use Utopia\DNS\Client;
|
||||
use Utopia\DNS\Message;
|
||||
use Utopia\DNS\Message\Question;
|
||||
use Swoole\Coroutine\WaitGroup;
|
||||
use Utopia\DNS\Message\Record;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator;
|
||||
use Utopia\DNS\Validator\DNS as BaseDNS;
|
||||
|
||||
class DNS extends Validator
|
||||
class DNS extends BaseDNS
|
||||
{
|
||||
public function __construct(
|
||||
protected string $target,
|
||||
protected int $type = Record::TYPE_CNAME,
|
||||
protected string $server = ''
|
||||
) {
|
||||
$this->server = $server ?: System::getEnv('_APP_DNS', '8.8.8.8');
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
protected array $dnsServers = [];
|
||||
|
||||
/**
|
||||
* @param string $target Expected value for the DNS record
|
||||
* @param int $type Type of DNS record to validate
|
||||
* For value, use const from Record, such as Record::TYPE_A
|
||||
* When using CAA type, you can provide exact match, or just issuer domain as $target
|
||||
* @param array<string> $dnsServers DNS server IP(s) or domain(s) to use for validation
|
||||
*/
|
||||
public function __construct(string $target, int $type = Record::TYPE_CNAME, array $dnsServers = [])
|
||||
{
|
||||
parent::__construct($target, $type, $dnsServers[0] ?? self::DEFAULT_DNS_SERVER);
|
||||
|
||||
$this->dnsServers = $dnsServers;
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
/**
|
||||
* Validate DNS record value against multiple DNS servers
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid(mixed $value): bool
|
||||
{
|
||||
return 'Invalid DNS record.';
|
||||
}
|
||||
$wg = new WaitGroup();
|
||||
$failedValidator = null;
|
||||
|
||||
public function isValid($value): bool
|
||||
{
|
||||
if (!is_string($value) || trim($value) === '') {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->dnsServers as $dnsServer) {
|
||||
$wg->add();
|
||||
|
||||
$client = new Client($this->server);
|
||||
try {
|
||||
$response = $client->query(Message::query(
|
||||
new Question($value, $this->type)
|
||||
));
|
||||
} catch (\Throwable) {
|
||||
return false;
|
||||
}
|
||||
\go(function () use ($value, $dnsServer, $wg, &$failedValidator) {
|
||||
try {
|
||||
$validator = new BaseDNS($this->target, $this->type, $dnsServer);
|
||||
$isValid = $validator->isValid($value);
|
||||
|
||||
$typeMatches = array_filter(
|
||||
$response->answers,
|
||||
fn (Record $record) => $record->type === $this->type
|
||||
);
|
||||
|
||||
if (empty($typeMatches)) {
|
||||
if ($this->type === Record::TYPE_CAA) {
|
||||
return $this->validateParentCAA($value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($typeMatches as $record) {
|
||||
if ($this->type === Record::TYPE_CAA) {
|
||||
$valuePart = $this->extractCAAValue($record->rdata);
|
||||
if ($valuePart !== '' && $valuePart === $this->target) {
|
||||
return true;
|
||||
if (!$isValid) {
|
||||
$failedValidator = $validator;
|
||||
}
|
||||
} finally {
|
||||
$wg->done();
|
||||
}
|
||||
}
|
||||
|
||||
if ($record->rdata === $this->target) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
$wg->wait();
|
||||
|
||||
private function validateParentCAA(string $domain): bool
|
||||
{
|
||||
try {
|
||||
$domainInfo = new Domain($domain);
|
||||
} catch (\Throwable) {
|
||||
if (!\is_null($failedValidator)) {
|
||||
$this->count = $failedValidator->count;
|
||||
$this->value = $failedValidator->value;
|
||||
$this->reason = $failedValidator->reason;
|
||||
$this->records = $failedValidator->records;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($domainInfo->get() === $domainInfo->getApex()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$parts = explode('.', $domainInfo->get());
|
||||
array_shift($parts);
|
||||
$parent = implode('.', $parts);
|
||||
|
||||
if ($parent === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$validator = new self($this->target, Record::TYPE_CAA, $this->server);
|
||||
return $validator->isValid($parent);
|
||||
}
|
||||
|
||||
private function extractCAAValue(string $rdata): string
|
||||
{
|
||||
$parts = explode(' ', $rdata, 3);
|
||||
if (count($parts) < 3) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = trim($parts[2], '"');
|
||||
return explode(';', $value)[0] ?? '';
|
||||
}
|
||||
|
||||
public function isArray(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return self::TYPE_STRING;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -4,7 +4,7 @@ namespace Appwrite\Platform\Modules\Compute;
|
||||
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Action;
|
||||
use Appwrite\Platform\Action as PlatformAction;
|
||||
use Appwrite\Platform\Modules\Compute\Validator\Specification as SpecificationValidator;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
@@ -19,7 +19,7 @@ use Utopia\System\System;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
use Utopia\VCS\Exception\RepositoryNotFound;
|
||||
|
||||
class Base extends Action
|
||||
class Action extends PlatformAction
|
||||
{
|
||||
/**
|
||||
* Get default specification based on plan and available specifications.
|
||||
@@ -252,7 +252,7 @@ class Base extends Action
|
||||
'deploymentResourceId' => $site->getId(),
|
||||
'deploymentResourceInternalId' => $site->getSequence(),
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
@@ -278,7 +278,7 @@ class Base extends Action
|
||||
'deploymentResourceId' => $site->getId(),
|
||||
'deploymentResourceInternalId' => $site->getSequence(),
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
@@ -315,7 +315,7 @@ class Base extends Action
|
||||
'deploymentResourceId' => $site->getId(),
|
||||
'deploymentResourceInternalId' => $site->getSequence(),
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
@@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Deployments;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -18,7 +19,6 @@ use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Storage\Validator\File;
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Deployments;
|
||||
use Appwrite\Event\Delete as DeleteEvent;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -14,7 +15,6 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Download;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -11,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Swoole\Request;
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Duplicate;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -12,7 +13,6 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Deployments;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
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\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Action
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Status;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -13,7 +14,6 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Update extends Action
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Template;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -16,7 +16,6 @@ use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Swoole\Request;
|
||||
use Utopia\Validator\Boolean;
|
||||
@@ -24,7 +23,7 @@ use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Vcs;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -13,7 +13,6 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Swoole\Request;
|
||||
use Utopia\Validator\Boolean;
|
||||
@@ -21,7 +20,7 @@ use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Deployments;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -17,12 +17,11 @@ use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Extend\Exception as AppwriteException;
|
||||
use Appwrite\Functions\Validator\Headers;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -29,7 +29,6 @@ use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Swoole\Request;
|
||||
use Utopia\System\System;
|
||||
@@ -40,7 +39,7 @@ use Utopia\Validator\Nullable;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Executions;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -15,10 +15,9 @@ use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Delete extends Base
|
||||
class Delete extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Executions;
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -12,10 +12,9 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Executions;
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -18,11 +18,10 @@ use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use Appwrite\Event\Realtime;
|
||||
use Appwrite\Event\Validator\FunctionEvent;
|
||||
use Appwrite\Event\Webhook;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\Platform\Modules\Compute\Validator\Specification;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -29,7 +29,6 @@ use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Roles;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Request;
|
||||
use Utopia\System\System;
|
||||
@@ -40,7 +39,7 @@ use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
@@ -371,7 +370,7 @@ class Create extends Base
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getSequence(),
|
||||
'domain' => $domain,
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'type' => 'deployment',
|
||||
'trigger' => 'manual',
|
||||
'deploymentId' => !isset($deployment) || $deployment->isEmpty() ? '' : $deployment->getId(),
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Functions;
|
||||
use Appwrite\Event\Delete as DeleteEvent;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -15,10 +15,9 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Delete extends Base
|
||||
class Delete extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Appwrite\Platform\Modules\Functions\Http\Functions\Deployment;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -15,10 +15,9 @@ 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;
|
||||
|
||||
class Update extends Base
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,17 +3,16 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Functions;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
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\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Validator\FunctionEvent;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\Platform\Modules\Compute\Validator\Specification;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -25,7 +25,6 @@ use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Roles;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Swoole\Request;
|
||||
use Utopia\System\System;
|
||||
@@ -37,7 +36,7 @@ use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
|
||||
class Update extends Base
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Functions;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -15,12 +15,11 @@ use Utopia\Database\Exception\Order as OrderException;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Runtimes;
|
||||
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Specifications;
|
||||
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Templates;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -2,21 +2,20 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Templates;
|
||||
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Usage;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -14,11 +14,10 @@ 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;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Usage;
|
||||
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -12,11 +12,10 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -17,12 +17,11 @@ use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -13,10 +13,9 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Delete extends Base
|
||||
class Delete extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,17 +3,16 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
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\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -13,13 +13,12 @@ use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Exception\Duplicate as DuplicateException;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Nullable;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Update extends Base
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -11,10 +11,9 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use Appwrite\Event\Realtime;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Event\Webhook;
|
||||
use Appwrite\Permission;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\Role;
|
||||
use Appwrite\Utopia\Response\Model\Deployment;
|
||||
use Appwrite\Vcs\Comment;
|
||||
@@ -33,7 +34,6 @@ use Utopia\Detector\Detection\Rendering\XStatic;
|
||||
use Utopia\Detector\Detector\Rendering;
|
||||
use Utopia\Fetch\Client as FetchClient;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Message;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
@@ -1226,7 +1226,7 @@ class Builds extends Action
|
||||
'deploymentResourceId' => $deployment->getId(),
|
||||
'deploymentResourceInternalId' => $deployment->getSequence(),
|
||||
'deploymentVcsProviderBranch' => $branchName,
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
namespace Appwrite\Platform\Modules\Projects;
|
||||
|
||||
use Appwrite\Platform\Modules\Projects\Services\Http;
|
||||
use Utopia\Platform\Module as Base;
|
||||
use Utopia\Platform\Module as PlatformModule;
|
||||
|
||||
class Module extends Base
|
||||
class Module extends PlatformModule
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Proxy;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\DNS as ValidatorDNS;
|
||||
use Appwrite\Platform\Action as PlatformAction;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\DNS\Message\Record;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\IP;
|
||||
|
||||
class Action extends PlatformAction
|
||||
{
|
||||
public function __construct(protected string $dnsValidatorClass = ValidatorDNS::class)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify or re-verify a rule
|
||||
*
|
||||
* @param Document $rule Rule to verify
|
||||
* @param Log|null $log Log instance to add timings to
|
||||
* @param string|null $verificationDomainAPI Override for expected API rule value during verification
|
||||
* @param string|null $verificationDomainFunction Override for expected Function rule value during verification
|
||||
* @return void
|
||||
*/
|
||||
public function verifyRule(Document $rule, ?Log $log = null, ?string $verificationDomainAPI = null, ?string $verificationDomainFunction = null): void
|
||||
{
|
||||
$dnsValidatorClass = $this->dnsValidatorClass;
|
||||
$dnsEnv = System::getEnv('_APP_DNS', '8.8.8.8');
|
||||
$servers = \array_map('trim', \explode(',', $dnsEnv));
|
||||
$dnsServers = \array_filter($servers, fn ($server) => !empty($server));
|
||||
|
||||
$domain = new Domain($rule->getAttribute('domain', ''));
|
||||
|
||||
if (empty($domain->get())) {
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED, 'DNS verification failed because domain is not valid.');
|
||||
}
|
||||
|
||||
if (!$domain->isKnown() || $domain->isTest()) {
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED, 'DNS verification failed because domain ' . $domain->get() . ' is not known public suffix.');
|
||||
}
|
||||
|
||||
// Ensure CAA won't block certificate issuance
|
||||
$caaTarget = System::getEnv('_APP_DOMAIN_TARGET_CAA', '');
|
||||
if (!empty($caaTarget)) {
|
||||
$validationStart = \microtime(true);
|
||||
$validator = new $dnsValidatorClass($caaTarget, Record::TYPE_CAA, $dnsServers);
|
||||
if (!$validator->isValid($domain->get())) {
|
||||
if (!\is_null($log)) {
|
||||
$log->addExtra('dnsTimingCaa', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
}
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED, $validator->getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure at least one of CNAME/A/AAAA record points to our servers properly
|
||||
// Ensures different target based on rule's type, as configured by env variables
|
||||
if (\is_null($verificationDomainAPI)) {
|
||||
$verificationDomainAPI = System::getEnv('_APP_DOMAIN_TARGET_CNAME', '');
|
||||
}
|
||||
if (\is_null($verificationDomainFunction)) {
|
||||
$verificationDomainFunction = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
}
|
||||
|
||||
$targetCNAME = null;
|
||||
$ruleType = $rule->getAttribute('type', '');
|
||||
$resourceType = $rule->getAttribute('deploymentResourceType', '');
|
||||
|
||||
if ($resourceType === 'function') {
|
||||
// For example: fra.appwrite.run
|
||||
$targetCNAME = new Domain($verificationDomainFunction);
|
||||
} elseif ($resourceType === 'site') {
|
||||
// For example: appwrite.network
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', ''));
|
||||
} elseif ($ruleType === 'api') {
|
||||
// For example: fra.cloud.appwrite.io
|
||||
$targetCNAME = new Domain($verificationDomainAPI);
|
||||
} elseif ($ruleType === 'redirect') {
|
||||
// Shouldn't be needed, because redirect should always have resourceTyp too, but just in case we defailt to sites
|
||||
// For example: appwrite.network
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', ''));
|
||||
}
|
||||
|
||||
$validators = [];
|
||||
$mainValidator = null; // Validator to use for error description
|
||||
|
||||
if (!is_null($targetCNAME)) {
|
||||
$validator = new $dnsValidatorClass($targetCNAME->get(), Record::TYPE_CNAME, $dnsServers);
|
||||
$validators[] = $validator;
|
||||
|
||||
if (\is_null($mainValidator)) {
|
||||
$mainValidator = $validator;
|
||||
}
|
||||
}
|
||||
|
||||
$targetA = System::getEnv('_APP_DOMAIN_TARGET_A', '');
|
||||
if ((new IP(IP::V4))->isValid($targetA)) {
|
||||
$validator = new $dnsValidatorClass($targetA, Record::TYPE_A, $dnsServers);
|
||||
$validators[] = $validator;
|
||||
|
||||
if (\is_null($mainValidator)) {
|
||||
$mainValidator = $validator;
|
||||
}
|
||||
}
|
||||
|
||||
$targetAAAA = System::getEnv('_APP_DOMAIN_TARGET_AAAA', '');
|
||||
if ((new IP(IP::V6))->isValid($targetAAAA)) {
|
||||
$validator = new $dnsValidatorClass($targetAAAA, Record::TYPE_AAAA, $dnsServers);
|
||||
$validators[] = $validator;
|
||||
|
||||
if (\is_null($mainValidator)) {
|
||||
$mainValidator = $validator;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($validators)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
|
||||
}
|
||||
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
|
||||
$validationStart = \microtime(true);
|
||||
if (!$validator->isValid($domain->get())) {
|
||||
if (!\is_null($log)) {
|
||||
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
}
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED, $mainValidator->getDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Proxy\Http\Rules\API;
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -14,14 +14,11 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\DNS\Message\Record;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\Domain as ValidatorDomain;
|
||||
use Utopia\Validator\IP;
|
||||
|
||||
class Create extends Action
|
||||
{
|
||||
@@ -32,8 +29,10 @@ class Create extends Action
|
||||
return 'createAPIRule';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
public function __construct(...$params)
|
||||
{
|
||||
parent::__construct(...$params);
|
||||
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
|
||||
->setHttpPath('/v1/proxy/rules/api')
|
||||
@@ -67,11 +66,19 @@ class Create extends Action
|
||||
->inject('queueForCertificates')
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForPlatform')
|
||||
->inject('log')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $domain, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform)
|
||||
{
|
||||
public function action(
|
||||
string $domain,
|
||||
Response $response,
|
||||
Document $project,
|
||||
Certificate $queueForCertificates,
|
||||
Event $queueForEvents,
|
||||
Database $dbForPlatform,
|
||||
Log $log
|
||||
) {
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
@@ -128,31 +135,9 @@ class Create extends Action
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
||||
|
||||
$status = 'created';
|
||||
$status = RULE_STATUS_VERIFICATION_FAILED;
|
||||
if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) {
|
||||
$status = 'verified';
|
||||
}
|
||||
if ($status === 'created') {
|
||||
$validators = [];
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
|
||||
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
|
||||
}
|
||||
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
|
||||
}
|
||||
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
|
||||
}
|
||||
|
||||
if (empty($validators)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
|
||||
}
|
||||
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
if ($validator->isValid($domain->get())) {
|
||||
$status = 'verifying';
|
||||
}
|
||||
$status = RULE_STATUS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
$owner = '';
|
||||
@@ -177,13 +162,22 @@ class Create extends Action
|
||||
'region' => $project->getAttribute('region')
|
||||
]);
|
||||
|
||||
if ($rule->getAttribute('status', '') === RULE_STATUS_VERIFICATION_FAILED) {
|
||||
try {
|
||||
$this->verifyRule($rule, $log);
|
||||
$rule->setAttribute('status', RULE_STATUS_GENERATING_CERTIFICATE);
|
||||
} catch (Exception $err) {
|
||||
$rule->setAttribute('logs', $err->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$rule = $dbForPlatform->createDocument('rules', $rule);
|
||||
} catch (Duplicate $e) {
|
||||
throw new Exception(Exception::RULE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if ($rule->getAttribute('status', '') === 'verifying') {
|
||||
if ($rule->getAttribute('status', '') === RULE_STATUS_GENERATING_CERTIFICATE) {
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain'),
|
||||
@@ -194,6 +188,22 @@ class Create extends Action
|
||||
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
$certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', ''));
|
||||
|
||||
// Merge logs: priority to certificate logs if both have values, otherwise use whichever is not empty
|
||||
$ruleLogs = $rule->getAttribute('logs', '');
|
||||
$certificateLogs = $certificate->getAttribute('logs', '');
|
||||
$logs = '';
|
||||
if (!empty($certificateLogs) && !empty($ruleLogs)) {
|
||||
$logs = $certificateLogs; // Certificate logs have priority
|
||||
} elseif (!empty($certificateLogs)) {
|
||||
$logs = $certificateLogs;
|
||||
} elseif (!empty($ruleLogs)) {
|
||||
$logs = $ruleLogs;
|
||||
}
|
||||
$rule->setAttribute('logs', $logs);
|
||||
$rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', ''));
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Proxy\Http\Rules;
|
||||
use Appwrite\Event\Delete as DeleteEvent;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -13,7 +14,6 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Delete extends Action
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Proxy\Http\Rules\Function;
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -15,14 +15,11 @@ use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\DNS\Message\Record;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\Domain as ValidatorDomain;
|
||||
use Utopia\Validator\IP;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Create extends Action
|
||||
@@ -34,8 +31,10 @@ class Create extends Action
|
||||
return 'createFunctionRule';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
public function __construct(...$params)
|
||||
{
|
||||
parent::__construct(...$params);
|
||||
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
|
||||
->setHttpPath('/v1/proxy/rules/function')
|
||||
@@ -72,11 +71,22 @@ class Create extends Action
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForPlatform')
|
||||
->inject('dbForProject')
|
||||
->inject('log')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $domain, string $functionId, string $branch, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject)
|
||||
{
|
||||
public function action(
|
||||
string $domain,
|
||||
string $functionId,
|
||||
string $branch,
|
||||
Response $response,
|
||||
Document $project,
|
||||
Certificate $queueForCertificates,
|
||||
Event $queueForEvents,
|
||||
Database $dbForPlatform,
|
||||
Database $dbForProject,
|
||||
Log $log
|
||||
) {
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
@@ -140,31 +150,9 @@ class Create extends Action
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
||||
|
||||
$status = 'created';
|
||||
$status = RULE_STATUS_VERIFICATION_FAILED;
|
||||
if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) {
|
||||
$status = 'verified';
|
||||
}
|
||||
if ($status === 'created') {
|
||||
$validators = [];
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
|
||||
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
|
||||
}
|
||||
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
|
||||
}
|
||||
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
|
||||
}
|
||||
|
||||
if (empty($validators)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
|
||||
}
|
||||
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
if ($validator->isValid($domain->get())) {
|
||||
$status = 'verifying';
|
||||
}
|
||||
$status = RULE_STATUS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
$owner = '';
|
||||
@@ -195,13 +183,22 @@ class Create extends Action
|
||||
'region' => $project->getAttribute('region')
|
||||
]);
|
||||
|
||||
if ($rule->getAttribute('status', '') === RULE_STATUS_VERIFICATION_FAILED) {
|
||||
try {
|
||||
$this->verifyRule($rule, $log);
|
||||
$rule->setAttribute('status', RULE_STATUS_GENERATING_CERTIFICATE);
|
||||
} catch (Exception $err) {
|
||||
$rule->setAttribute('logs', $err->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$rule = $dbForPlatform->createDocument('rules', $rule);
|
||||
} catch (Duplicate $e) {
|
||||
throw new Exception(Exception::RULE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if ($rule->getAttribute('status', '') === 'verifying') {
|
||||
if ($rule->getAttribute('status', '') === RULE_STATUS_GENERATING_CERTIFICATE) {
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain'),
|
||||
@@ -212,6 +209,22 @@ class Create extends Action
|
||||
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
$certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', ''));
|
||||
|
||||
// Merge logs: priority to certificate logs if both have values, otherwise use whichever is not empty
|
||||
$ruleLogs = $rule->getAttribute('logs', '');
|
||||
$certificateLogs = $certificate->getAttribute('logs', '');
|
||||
$logs = '';
|
||||
if (!empty($certificateLogs) && !empty($ruleLogs)) {
|
||||
$logs = $certificateLogs; // Certificate logs have priority
|
||||
} elseif (!empty($certificateLogs)) {
|
||||
$logs = $certificateLogs;
|
||||
} elseif (!empty($ruleLogs)) {
|
||||
$logs = $ruleLogs;
|
||||
}
|
||||
$rule->setAttribute('logs', $logs);
|
||||
$rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', ''));
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Proxy\Http\Rules;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -10,7 +11,6 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Action
|
||||
@@ -64,8 +64,21 @@ class Get extends Action
|
||||
throw new Exception(Exception::RULE_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Fill response model
|
||||
$certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', ''));
|
||||
$rule->setAttribute('logs', $certificate->getAttribute('logs', ''));
|
||||
|
||||
// Merge logs: priority to certificate logs if both have values, otherwise use whichever is not empty
|
||||
$ruleLogs = $rule->getAttribute('logs', '');
|
||||
$certificateLogs = $certificate->getAttribute('logs', '');
|
||||
$logs = '';
|
||||
if (!empty($certificateLogs) && !empty($ruleLogs)) {
|
||||
$logs = $certificateLogs; // Certificate logs have priority
|
||||
} elseif (!empty($certificateLogs)) {
|
||||
$logs = $certificateLogs;
|
||||
} elseif (!empty($ruleLogs)) {
|
||||
$logs = $ruleLogs;
|
||||
}
|
||||
$rule->setAttribute('logs', $logs);
|
||||
$rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', ''));
|
||||
|
||||
$response->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Proxy\Http\Rules\Redirect;
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -15,14 +15,11 @@ use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\DNS\Message\Record;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\Domain as ValidatorDomain;
|
||||
use Utopia\Validator\IP;
|
||||
use Utopia\Validator\URL;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
@@ -35,8 +32,10 @@ class Create extends Action
|
||||
return 'createRedirectRule';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
public function __construct(...$params)
|
||||
{
|
||||
parent::__construct(...$params);
|
||||
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
|
||||
->setHttpPath('/v1/proxy/rules/redirect')
|
||||
@@ -75,11 +74,24 @@ class Create extends Action
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForPlatform')
|
||||
->inject('dbForProject')
|
||||
->inject('log')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $domain, string $url, int $statusCode, string $resourceId, string $resourceType, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject)
|
||||
{
|
||||
public function action(
|
||||
string $domain,
|
||||
string $url,
|
||||
int $statusCode,
|
||||
string $resourceId,
|
||||
string $resourceType,
|
||||
Response $response,
|
||||
Document $project,
|
||||
Certificate $queueForCertificates,
|
||||
Event $queueForEvents,
|
||||
Database $dbForPlatform,
|
||||
Database $dbForProject,
|
||||
Log $log
|
||||
) {
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
@@ -145,31 +157,9 @@ class Create extends Action
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
||||
|
||||
$status = 'created';
|
||||
$status = RULE_STATUS_VERIFICATION_FAILED;
|
||||
if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) {
|
||||
$status = 'verified';
|
||||
}
|
||||
if ($status === 'created') {
|
||||
$validators = [];
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
|
||||
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
|
||||
}
|
||||
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
|
||||
}
|
||||
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
|
||||
}
|
||||
|
||||
if (empty($validators)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
|
||||
}
|
||||
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
if ($validator->isValid($domain->get())) {
|
||||
$status = 'verifying';
|
||||
}
|
||||
$status = RULE_STATUS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
$owner = '';
|
||||
@@ -199,13 +189,22 @@ class Create extends Action
|
||||
'region' => $project->getAttribute('region')
|
||||
]);
|
||||
|
||||
if ($rule->getAttribute('status', '') === RULE_STATUS_VERIFICATION_FAILED) {
|
||||
try {
|
||||
$this->verifyRule($rule, $log);
|
||||
$rule->setAttribute('status', RULE_STATUS_GENERATING_CERTIFICATE);
|
||||
} catch (Exception $err) {
|
||||
$rule->setAttribute('logs', $err->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$rule = $dbForPlatform->createDocument('rules', $rule);
|
||||
} catch (Duplicate $e) {
|
||||
throw new Exception(Exception::RULE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if ($rule->getAttribute('status', '') === 'verifying') {
|
||||
if ($rule->getAttribute('status', '') === RULE_STATUS_GENERATING_CERTIFICATE) {
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain'),
|
||||
@@ -216,6 +215,22 @@ class Create extends Action
|
||||
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
$certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', ''));
|
||||
|
||||
// Merge logs: priority to certificate logs if both have values, otherwise use whichever is not empty
|
||||
$ruleLogs = $rule->getAttribute('logs', '');
|
||||
$certificateLogs = $certificate->getAttribute('logs', '');
|
||||
$logs = '';
|
||||
if (!empty($certificateLogs) && !empty($ruleLogs)) {
|
||||
$logs = $certificateLogs; // Certificate logs have priority
|
||||
} elseif (!empty($certificateLogs)) {
|
||||
$logs = $certificateLogs;
|
||||
} elseif (!empty($ruleLogs)) {
|
||||
$logs = $ruleLogs;
|
||||
}
|
||||
$rule->setAttribute('logs', $logs);
|
||||
$rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', ''));
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Proxy\Http\Rules\Site;
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -15,14 +15,11 @@ use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\DNS\Message\Record;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\Domain as ValidatorDomain;
|
||||
use Utopia\Validator\IP;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Create extends Action
|
||||
@@ -34,8 +31,10 @@ class Create extends Action
|
||||
return 'createSiteRule';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
public function __construct(...$params)
|
||||
{
|
||||
parent::__construct(...$params);
|
||||
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
|
||||
->setHttpPath('/v1/proxy/rules/site')
|
||||
@@ -72,11 +71,22 @@ class Create extends Action
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForPlatform')
|
||||
->inject('dbForProject')
|
||||
->inject('log')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $domain, string $siteId, string $branch, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject)
|
||||
{
|
||||
public function action(
|
||||
string $domain,
|
||||
string $siteId,
|
||||
string $branch,
|
||||
Response $response,
|
||||
Document $project,
|
||||
Certificate $queueForCertificates,
|
||||
Event $queueForEvents,
|
||||
Database $dbForPlatform,
|
||||
Database $dbForProject,
|
||||
Log $log
|
||||
) {
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
@@ -140,31 +150,9 @@ class Create extends Action
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
||||
|
||||
$status = 'created';
|
||||
$status = RULE_STATUS_VERIFICATION_FAILED;
|
||||
if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) {
|
||||
$status = 'verified';
|
||||
}
|
||||
if ($status === 'created') {
|
||||
$validators = [];
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
|
||||
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
|
||||
}
|
||||
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
|
||||
}
|
||||
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
|
||||
}
|
||||
|
||||
if (empty($validators)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
|
||||
}
|
||||
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
if ($validator->isValid($domain->get())) {
|
||||
$status = 'verifying';
|
||||
}
|
||||
$status = RULE_STATUS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
$owner = '';
|
||||
@@ -195,13 +183,22 @@ class Create extends Action
|
||||
'region' => $project->getAttribute('region')
|
||||
]);
|
||||
|
||||
if ($rule->getAttribute('status', '') === RULE_STATUS_VERIFICATION_FAILED) {
|
||||
try {
|
||||
$this->verifyRule($rule, $log);
|
||||
$rule->setAttribute('status', RULE_STATUS_GENERATING_CERTIFICATE);
|
||||
} catch (Exception $err) {
|
||||
$rule->setAttribute('logs', $err->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$rule = $dbForPlatform->createDocument('rules', $rule);
|
||||
} catch (Duplicate $e) {
|
||||
throw new Exception(Exception::RULE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if ($rule->getAttribute('status', '') === 'verifying') {
|
||||
if ($rule->getAttribute('status', '') === RULE_STATUS_GENERATING_CERTIFICATE) {
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain'),
|
||||
@@ -212,6 +209,22 @@ class Create extends Action
|
||||
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
$certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', ''));
|
||||
|
||||
// Merge logs: priority to certificate logs if both have values, otherwise use whichever is not empty
|
||||
$ruleLogs = $rule->getAttribute('logs', '');
|
||||
$certificateLogs = $certificate->getAttribute('logs', '');
|
||||
$logs = '';
|
||||
if (!empty($certificateLogs) && !empty($ruleLogs)) {
|
||||
$logs = $certificateLogs; // Certificate logs have priority
|
||||
} elseif (!empty($certificateLogs)) {
|
||||
$logs = $certificateLogs;
|
||||
} elseif (!empty($ruleLogs)) {
|
||||
$logs = $ruleLogs;
|
||||
}
|
||||
$rule->setAttribute('logs', $logs);
|
||||
$rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', ''));
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
|
||||
@@ -5,22 +5,18 @@ namespace Appwrite\Platform\Modules\Proxy\Http\Rules\Verification;
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
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\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\DNS\Message\Record;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\IP;
|
||||
|
||||
class Update extends Action
|
||||
{
|
||||
@@ -31,8 +27,10 @@ class Update extends Action
|
||||
return 'updateRuleVerification';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
public function __construct(...$params)
|
||||
{
|
||||
parent::__construct(...$params);
|
||||
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH)
|
||||
->setHttpPath('/v1/proxy/rules/:ruleId/verification')
|
||||
@@ -82,81 +80,28 @@ class Update extends Action
|
||||
throw new Exception(Exception::RULE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$targetCNAME = null;
|
||||
switch ($rule->getAttribute('type', '')) {
|
||||
case 'api':
|
||||
// For example: fra.cloud.appwrite.io
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
break;
|
||||
case 'redirect':
|
||||
// For example: appwrite.network
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', ''));
|
||||
break;
|
||||
case 'deployment':
|
||||
switch ($rule->getAttribute('deploymentResourceType', '')) {
|
||||
case 'function':
|
||||
// For example: fra.appwrite.run
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_FUNCTIONS', ''));
|
||||
break;
|
||||
case 'site':
|
||||
// For example: appwrite.network
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', ''));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
$validators = [];
|
||||
|
||||
if (!is_null($targetCNAME)) {
|
||||
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
|
||||
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
|
||||
}
|
||||
}
|
||||
|
||||
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
|
||||
}
|
||||
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
|
||||
}
|
||||
|
||||
if (empty($validators)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
|
||||
}
|
||||
|
||||
if ($rule->getAttribute('verification') === true) {
|
||||
if ($rule->getAttribute('status', '') !== RULE_STATUS_VERIFICATION_FAILED) {
|
||||
return $response->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
}
|
||||
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
$domain = new Domain($rule->getAttribute('domain', ''));
|
||||
$updates = new Document();
|
||||
|
||||
$validationStart = \microtime(true);
|
||||
if (!$validator->isValid($domain->get())) {
|
||||
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED);
|
||||
try {
|
||||
$this->verifyRule($rule, $log);
|
||||
$updates->setAttribute('logs', '');
|
||||
} catch (Exception $err) {
|
||||
$dbForPlatform->updateDocument('rules', $rule->getId(), new Document([
|
||||
'$updatedAt' => DateTime::now(),
|
||||
'logs' => $err->getMessage(),
|
||||
]));
|
||||
throw $err;
|
||||
}
|
||||
|
||||
// Ensure CAA won't block certificate issuance
|
||||
if (!empty(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''))) {
|
||||
$validationStart = \microtime(true);
|
||||
$validator = new DNS(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''), Record::TYPE_CAA);
|
||||
if (!$validator->isValid($domain->get())) {
|
||||
$log->addExtra('dnsTimingCaa', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
$error = $validator->getDescription();
|
||||
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED, 'Domain verification failed because CAA records do not allow Appwrite\'s certificate issuer.');
|
||||
}
|
||||
}
|
||||
$updates->setAttribute('status', RULE_STATUS_GENERATING_CERTIFICATE);
|
||||
|
||||
$dbForPlatform->updateDocument('rules', $rule->getId(), $rule->setAttribute('status', 'verifying'));
|
||||
$rule = $dbForPlatform->updateDocument('rules', $rule->getId(), $updates);
|
||||
|
||||
// Issue a TLS certificate when domain is verified
|
||||
$queueForCertificates
|
||||
@@ -166,10 +111,22 @@ class Update extends Action
|
||||
]))
|
||||
->trigger();
|
||||
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
// Fill response model
|
||||
$certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', ''));
|
||||
$rule->setAttribute('logs', $certificate->getAttribute('logs', ''));
|
||||
|
||||
// Merge logs: priority to certificate logs if both have values, otherwise use whichever is not empty
|
||||
$ruleLogs = $rule->getAttribute('logs', '');
|
||||
$certificateLogs = $certificate->getAttribute('logs', '');
|
||||
$logs = '';
|
||||
if (!empty($certificateLogs) && !empty($ruleLogs)) {
|
||||
$logs = $certificateLogs;
|
||||
} elseif (!empty($certificateLogs)) {
|
||||
$logs = $certificateLogs;
|
||||
} elseif (!empty($ruleLogs)) {
|
||||
$logs = $ruleLogs;
|
||||
}
|
||||
$rule->setAttribute('logs', $logs);
|
||||
$rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', ''));
|
||||
|
||||
$response->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Proxy\Http\Rules;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -13,7 +14,6 @@ use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
@@ -107,9 +107,23 @@ class XList extends Action
|
||||
$filterQueries = Query::groupByType($queries)['filters'];
|
||||
|
||||
$rules = $dbForPlatform->find('rules', $queries);
|
||||
|
||||
// Fill response model
|
||||
foreach ($rules as $rule) {
|
||||
$certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', ''));
|
||||
$rule->setAttribute('logs', $certificate->getAttribute('logs', ''));
|
||||
|
||||
// Merge logs: priority to certificate logs if both have values, otherwise use whichever is not empty
|
||||
$ruleLogs = $rule->getAttribute('logs', '');
|
||||
$certificateLogs = $certificate->getAttribute('logs', '');
|
||||
$logs = '';
|
||||
if (!empty($certificateLogs) && !empty($ruleLogs)) {
|
||||
$logs = $certificateLogs; // Certificate logs have priority
|
||||
} elseif (!empty($certificateLogs)) {
|
||||
$logs = $certificateLogs;
|
||||
} elseif (!empty($ruleLogs)) {
|
||||
$logs = $ruleLogs;
|
||||
}
|
||||
$rule->setAttribute('logs', $logs);
|
||||
$rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', ''));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -19,7 +20,6 @@ use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Storage\Validator\File;
|
||||
@@ -288,7 +288,7 @@ class Create extends Action
|
||||
'deploymentResourceType' => 'site',
|
||||
'deploymentResourceId' => $site->getId(),
|
||||
'deploymentResourceInternalId' => $site->getSequence(),
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
@@ -353,7 +353,7 @@ class Create extends Action
|
||||
'deploymentResourceType' => 'site',
|
||||
'deploymentResourceId' => $site->getId(),
|
||||
'deploymentResourceInternalId' => $site->getSequence(),
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
use Appwrite\Event\Delete as DeleteEvent;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -14,7 +15,6 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Download;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -11,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Swoole\Request;
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Duplicate;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -14,7 +15,6 @@ use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Swoole\Request;
|
||||
@@ -159,7 +159,7 @@ class Create extends Action
|
||||
'deploymentResourceType' => 'site',
|
||||
'deploymentResourceId' => $site->getId(),
|
||||
'deploymentResourceInternalId' => $site->getSequence(),
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'owner' => 'Appwrite',
|
||||
'region' => $project->getAttribute('region')
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
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\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Action
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Status;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -13,7 +14,6 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Update extends Action
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Template;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -17,7 +17,6 @@ use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Swoole\Request;
|
||||
use Utopia\System\System;
|
||||
@@ -26,7 +25,7 @@ use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
@@ -201,7 +200,7 @@ class Create extends Base
|
||||
'deploymentResourceType' => 'site',
|
||||
'deploymentResourceId' => $site->getId(),
|
||||
'deploymentResourceInternalId' => $site->getSequence(),
|
||||
'status' => 'verified',
|
||||
'status' => RULE_STATUS_SUCCESSFUL,
|
||||
'certificateId' => '',
|
||||
'owner' => 'Appwrite',
|
||||
'region' => $project->getAttribute('region')
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Vcs;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -13,7 +13,6 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Swoole\Request;
|
||||
use Utopia\Validator\Boolean;
|
||||
@@ -21,7 +20,7 @@ use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -17,12 +17,11 @@ use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -2,17 +2,16 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Frameworks;
|
||||
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -4,17 +4,16 @@ namespace Appwrite\Platform\Modules\Sites\Http\Logs;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
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\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Delete extends Base
|
||||
class Delete extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,17 +3,16 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Logs;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
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\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Logs;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -17,11 +17,10 @@ use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Sites;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\Platform\Modules\Compute\Validator\Specification;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -17,7 +17,6 @@ use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Boolean;
|
||||
@@ -25,7 +24,7 @@ use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Sites;
|
||||
use Appwrite\Event\Delete as DeleteEvent;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -13,10 +13,9 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Delete extends Base
|
||||
class Delete extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Sites\Deployment;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -14,10 +14,9 @@ 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;
|
||||
|
||||
class Update extends Base
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,17 +3,16 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Sites;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
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\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Appwrite\Platform\Modules\Sites\Http\Sites;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\Platform\Modules\Compute\Validator\Specification;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -20,7 +20,6 @@ use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Swoole\Request;
|
||||
use Utopia\System\System;
|
||||
@@ -30,7 +29,7 @@ use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
|
||||
class Update extends Base
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Sites;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -15,12 +15,11 @@ use Utopia\Database\Exception\Order as OrderException;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Specifications;
|
||||
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Templates;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Templates;
|
||||
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Usage;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -14,11 +14,10 @@ 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;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Usage;
|
||||
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -12,11 +12,10 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -15,12 +15,11 @@ use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Create extends Base
|
||||
class Create extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -11,10 +11,9 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Delete extends Base
|
||||
class Delete extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,17 +3,16 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
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\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class Get extends Base
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -11,13 +11,12 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Exception\Duplicate as DuplicateException;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Nullable;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Update extends Base
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Variables;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Compute\Base;
|
||||
use Appwrite\Platform\Modules\Compute\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
@@ -11,10 +11,9 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class XList extends Base
|
||||
class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Appwrite\Platform\Services;
|
||||
|
||||
use Appwrite\Platform\Tasks\Doctor;
|
||||
use Appwrite\Platform\Tasks\Install;
|
||||
use Appwrite\Platform\Tasks\Interval;
|
||||
use Appwrite\Platform\Tasks\Maintenance;
|
||||
use Appwrite\Platform\Tasks\Migrate;
|
||||
use Appwrite\Platform\Tasks\QueueRetry;
|
||||
@@ -28,6 +29,7 @@ class Tasks extends Service
|
||||
$this
|
||||
->addAction(Doctor::getName(), new Doctor())
|
||||
->addAction(Install::getName(), new Install())
|
||||
->addAction(Interval::getName(), new Interval())
|
||||
->addAction(Maintenance::getName(), new Maintenance())
|
||||
->addAction(Migrate::getName(), new Migrate())
|
||||
->addAction(QueueRetry::getName(), new QueueRetry())
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Tasks;
|
||||
|
||||
use Appwrite\Event\Certificate;
|
||||
use DateTime;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime as DatabaseDateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\System\System;
|
||||
|
||||
class Interval extends Action
|
||||
{
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'interval';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->desc('Schedules interval tasks for rules verification and certificate renewal')
|
||||
->inject('dbForPlatform')
|
||||
->inject('queueForCertificates')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(Database $dbForPlatform, Certificate $queueForCertificates): void
|
||||
{
|
||||
Console::title('Interval V1');
|
||||
Console::success(APP_NAME . ' interval process v1 has started');
|
||||
|
||||
$intervalRuleVerification = (int) System::getEnv('_APP_MAINTENANCE_INTERVAL_RULE_VERIFICATION', '60'); // 1 minute
|
||||
$intervalCertificateRenewal = (int) System::getEnv('_APP_MAINTENANCE_INTERVAL', '86400'); // 1 day
|
||||
|
||||
\go(function () use ($dbForPlatform, $queueForCertificates, $intervalRuleVerification) {
|
||||
Console::loop(function () use ($dbForPlatform, $queueForCertificates) {
|
||||
$this->checkRuleVerification($dbForPlatform, $queueForCertificates);
|
||||
}, $intervalRuleVerification);
|
||||
});
|
||||
|
||||
\go(function () use ($dbForPlatform, $queueForCertificates, $intervalCertificateRenewal) {
|
||||
Console::loop(function () use ($dbForPlatform, $queueForCertificates) {
|
||||
$this->renewCertificates($dbForPlatform, $queueForCertificates);
|
||||
}, $intervalCertificateRenewal);
|
||||
});
|
||||
}
|
||||
|
||||
private function checkRuleVerification(Database $dbForPlatform, Certificate $queueForCertificate): void
|
||||
{
|
||||
$time = DatabaseDateTime::now();
|
||||
|
||||
$oldestToCheck = new DateTime('-3 days');
|
||||
|
||||
$rules = $dbForPlatform->find('rules', [
|
||||
Query::createdAfter(DatabaseDateTime::format($oldestToCheck)), // max 3 days old
|
||||
Query::equal('status', [RULE_STATUS_VERIFICATION_FAILED]), // not verified yet
|
||||
Query::orderAsc('$updatedAt'), // Pick the ones waiting for another attempt for longest
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')]), // Only current region
|
||||
Query::limit(30), // Reasonable pagination limit, processable within a minute
|
||||
]);
|
||||
|
||||
if (\count($rules) > 0) {
|
||||
Console::info("[{$time}] Found " . \count($rules) . " rules for verification, scheduling jobs.");
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
$queueForCertificate
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain'),
|
||||
'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')),
|
||||
]))
|
||||
->setAction(Certificate::ACTION_VERIFICATION)
|
||||
->trigger();
|
||||
}
|
||||
} else {
|
||||
// Silenced because interval makes it too often
|
||||
// Console::log("[{$time}] No rules for checking verification status.");
|
||||
}
|
||||
}
|
||||
|
||||
private function renewCertificates(Database $dbForPlatform, Certificate $queueForCertificate): void
|
||||
{
|
||||
$time = DatabaseDateTime::now();
|
||||
|
||||
$certificates = $dbForPlatform->find('certificates', [
|
||||
Query::lessThan('attempts', 5), // Maximum 5 attempts
|
||||
Query::isNotNull('renewDate'),
|
||||
Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew)
|
||||
Query::limit(200), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains)
|
||||
]);
|
||||
|
||||
if (\count($certificates) > 0) {
|
||||
Console::info("[{$time}] Found " . \count($certificates) . " certificates for renewal, scheduling jobs.");
|
||||
|
||||
foreach ($certificates as $certificate) {
|
||||
$domain = $certificate->getAttribute('domain');
|
||||
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
|
||||
$rule = $dbForPlatform->getDocument('rules', md5($domain));
|
||||
} else {
|
||||
$rule = $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$domain]),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($rule->isEmpty() || $rule->getAttribute('region') !== System::getEnv('_APP_REGION', 'default')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$queueForCertificate
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain'),
|
||||
'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')),
|
||||
]))
|
||||
->setAction(Certificate::ACTION_GENERATION)
|
||||
->trigger();
|
||||
}
|
||||
} else {
|
||||
Console::info("[{$time}] No certificates for renewal.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Appwrite\Platform\Tasks;
|
||||
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Delete;
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
@@ -27,17 +26,17 @@ class Maintenance extends Action
|
||||
->desc('Schedules maintenance tasks and publishes them to our queues')
|
||||
->inject('dbForPlatform')
|
||||
->inject('console')
|
||||
->inject('queueForCertificates')
|
||||
->inject('queueForDeletes')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(Database $dbForPlatform, Document $console, Certificate $queueForCertificates, Delete $queueForDeletes): void
|
||||
public function action(Database $dbForPlatform, Document $console, Delete $queueForDeletes): void
|
||||
{
|
||||
Console::title('Maintenance V1');
|
||||
Console::success(APP_NAME . ' maintenance process v1 has started');
|
||||
|
||||
$interval = (int) System::getEnv('_APP_MAINTENANCE_INTERVAL', '86400'); // 1 day
|
||||
|
||||
$usageStatsRetentionHourly = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_USAGE_HOURLY', '8640000'); //100 days
|
||||
$cacheRetention = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_CACHE', '2592000'); // 30 days
|
||||
$schedulesDeletionRetention = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_SCHEDULES', '86400'); // 1 Day
|
||||
@@ -59,44 +58,45 @@ class Maintenance extends Action
|
||||
|
||||
Console::info('Setting loop start time to ' . $next->format("Y-m-d H:i:s.v") . '. Delaying for ' . $delay . ' seconds.');
|
||||
|
||||
Console::loop(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForPlatform, $console, $queueForDeletes, $queueForCertificates) {
|
||||
$time = DatabaseDateTime::now();
|
||||
\go(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForPlatform, $console, $queueForDeletes, $delay) {
|
||||
Console::loop(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForPlatform, $console, $queueForDeletes) {
|
||||
$time = DatabaseDateTime::now();
|
||||
|
||||
Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds");
|
||||
Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds");
|
||||
|
||||
// Iterate through project only if it was accessed in last 30 days
|
||||
$dateInterval = DateInterval::createFromDateString('30 days');
|
||||
$before30days = (new DateTime())->sub($dateInterval);
|
||||
// Iterate through project only if it was accessed in last 30 days
|
||||
$dateInterval = DateInterval::createFromDateString('30 days');
|
||||
$before30days = (new DateTime())->sub($dateInterval);
|
||||
|
||||
$dbForPlatform->foreach(
|
||||
'projects',
|
||||
function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) {
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_MAINTENANCE)
|
||||
->setProject($project)
|
||||
->setUsageRetentionHourlyDateTime(DatabaseDateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly))
|
||||
->trigger();
|
||||
},
|
||||
[
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')]),
|
||||
Query::limit(100),
|
||||
Query::greaterThanEqual('accessedAt', DatabaseDateTime::format($before30days)),
|
||||
Query::orderAsc('teamInternalId'),
|
||||
]
|
||||
);
|
||||
$dbForPlatform->foreach(
|
||||
'projects',
|
||||
function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) {
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_MAINTENANCE)
|
||||
->setProject($project)
|
||||
->setUsageRetentionHourlyDateTime(DatabaseDateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly))
|
||||
->trigger();
|
||||
},
|
||||
[
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')]),
|
||||
Query::limit(100),
|
||||
Query::greaterThanEqual('accessedAt', DatabaseDateTime::format($before30days)),
|
||||
Query::orderAsc('teamInternalId'),
|
||||
]
|
||||
);
|
||||
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_MAINTENANCE)
|
||||
->setProject($console)
|
||||
->setUsageRetentionHourlyDateTime(DatabaseDateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly))
|
||||
->trigger();
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_MAINTENANCE)
|
||||
->setProject($console)
|
||||
->setUsageRetentionHourlyDateTime(DatabaseDateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly))
|
||||
->trigger();
|
||||
|
||||
$this->notifyDeleteConnections($queueForDeletes);
|
||||
$this->renewCertificates($dbForPlatform, $queueForCertificates);
|
||||
$this->notifyDeleteCache($cacheRetention, $queueForDeletes);
|
||||
$this->notifyDeleteSchedules($schedulesDeletionRetention, $queueForDeletes);
|
||||
$this->notifyDeleteCSVExports($queueForDeletes);
|
||||
}, $interval, $delay);
|
||||
$this->notifyDeleteConnections($queueForDeletes);
|
||||
$this->notifyDeleteCache($cacheRetention, $queueForDeletes);
|
||||
$this->notifyDeleteSchedules($schedulesDeletionRetention, $queueForDeletes);
|
||||
$this->notifyDeleteCSVExports($queueForDeletes);
|
||||
}, $interval, $delay);
|
||||
});
|
||||
}
|
||||
|
||||
private function notifyDeleteConnections(Delete $queueForDeletes): void
|
||||
@@ -114,46 +114,6 @@ class Maintenance extends Action
|
||||
->trigger();
|
||||
}
|
||||
|
||||
private function renewCertificates(Database $dbForPlatform, Certificate $queueForCertificate): void
|
||||
{
|
||||
$time = DatabaseDateTime::now();
|
||||
|
||||
$certificates = $dbForPlatform->find('certificates', [
|
||||
Query::lessThan('attempts', 5), // Maximum 5 attempts
|
||||
Query::isNotNull('renewDate'),
|
||||
Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew)
|
||||
Query::limit(200), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains)
|
||||
]);
|
||||
|
||||
|
||||
if (\count($certificates) > 0) {
|
||||
Console::info("[{$time}] Found " . \count($certificates) . " certificates for renewal, scheduling jobs.");
|
||||
|
||||
foreach ($certificates as $certificate) {
|
||||
$domain = $certificate->getAttribute('domain');
|
||||
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
|
||||
$rule = $dbForPlatform->getDocument('rules', md5($domain));
|
||||
} else {
|
||||
$rule = $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$domain]),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($rule->isEmpty() || $rule->getAttribute('region') !== System::getEnv('_APP_REGION', 'default')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$queueForCertificate
|
||||
->setDomain(new Document([
|
||||
'domain' => $certificate->getAttribute('domain')
|
||||
]))
|
||||
->trigger();
|
||||
}
|
||||
} else {
|
||||
Console::info("[{$time}] No certificates for renewal.");
|
||||
}
|
||||
}
|
||||
|
||||
private function notifyDeleteCache($interval, Delete $queueForDeletes): void
|
||||
{
|
||||
$queueForDeletes
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
namespace Appwrite\Platform\Workers;
|
||||
|
||||
use Appwrite\Certificates\Adapter as CertificatesAdapter;
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Func;
|
||||
use Appwrite\Event\Mail;
|
||||
use Appwrite\Event\Realtime;
|
||||
use Appwrite\Event\Webhook;
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\Extend\Exception as ExtendException;
|
||||
use Appwrite\Platform\Modules\Proxy\Action;
|
||||
use Appwrite\Template\Template;
|
||||
use Appwrite\Utopia\Response\Model\Rule;
|
||||
use Exception;
|
||||
@@ -22,15 +24,12 @@ use Utopia\Database\Exception\Conflict;
|
||||
use Utopia\Database\Exception\Structure;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\DNS\Message\Record;
|
||||
use Utopia\Database\Validator\Authorization as ValidatorAuthorization;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Message;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\IP;
|
||||
|
||||
class Certificates extends Action
|
||||
{
|
||||
@@ -42,8 +41,10 @@ class Certificates extends Action
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
public function __construct(...$params)
|
||||
{
|
||||
parent::__construct(...$params);
|
||||
|
||||
$this
|
||||
->desc('Certificates worker')
|
||||
->inject('message')
|
||||
@@ -53,6 +54,7 @@ class Certificates extends Action
|
||||
->inject('queueForWebhooks')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForRealtime')
|
||||
->inject('queueForCertificates')
|
||||
->inject('log')
|
||||
->inject('certificates')
|
||||
->inject('plan')
|
||||
@@ -67,6 +69,7 @@ class Certificates extends Action
|
||||
* @param Webhook $queueForWebhooks
|
||||
* @param Func $queueForFunctions
|
||||
* @param Realtime $queueForRealtime
|
||||
* @param Certificate $queueForCertificates
|
||||
* @param Log $log
|
||||
* @param CertificatesAdapter $certificates
|
||||
* @return void
|
||||
@@ -81,26 +84,102 @@ class Certificates extends Action
|
||||
Webhook $queueForWebhooks,
|
||||
Func $queueForFunctions,
|
||||
Realtime $queueForRealtime,
|
||||
Certificate $queueForCertificates,
|
||||
Log $log,
|
||||
CertificatesAdapter $certificates,
|
||||
array $plan
|
||||
): void {
|
||||
$payload = $message->getPayload() ?? [];
|
||||
|
||||
if (empty($payload)) {
|
||||
throw new Exception('Missing payload');
|
||||
}
|
||||
|
||||
$document = new Document($payload['domain'] ?? []);
|
||||
$domain = new Domain($document->getAttribute('domain', ''));
|
||||
$domain = new Domain($document->getAttribute('domain', ''));
|
||||
$domainType = $document->getAttribute('domainType');
|
||||
|
||||
$skipRenewCheck = $payload['skipRenewCheck'] ?? false;
|
||||
$validationDomain = $payload['validationDomain'] ?? null;
|
||||
$action = $payload['action'] ?? Certificate::ACTION_GENERATION;
|
||||
$verificationDomainFunction = $payload['verificationDomainFunction'] ?? null;
|
||||
$verificationDomainAPI = $payload['verificationDomainAPI'] ?? null;
|
||||
|
||||
Console::log('Received ' . $action . ' action for ' . $domain->get() . ' domain');
|
||||
|
||||
$log->addTag('domain', $domain->get());
|
||||
|
||||
$domainType = $document->getAttribute('domainType');
|
||||
switch ($action) {
|
||||
case Certificate::ACTION_GENERATION:
|
||||
$this->executeGeneration($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan, $verificationDomainFunction, $verificationDomainAPI);
|
||||
break;
|
||||
case Certificate::ACTION_VERIFICATION:
|
||||
$this->executeVerification($domain, $dbForPlatform, $log, $queueForCertificates, $verificationDomainFunction, $verificationDomainAPI);
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Invalid action: ' . $action);
|
||||
}
|
||||
}
|
||||
|
||||
$this->execute($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan, $validationDomain);
|
||||
private function executeVerification(
|
||||
Domain $domain,
|
||||
Database $dbForPlatform,
|
||||
Log $log,
|
||||
Certificate $queueForCertificates,
|
||||
?string $verificationDomainFunction = null,
|
||||
?string $verificationDomainAPI = null,
|
||||
): void {
|
||||
// Get rule
|
||||
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
|
||||
$rule = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get())));
|
||||
} else {
|
||||
$rule = ValidatorAuthorization::skip(
|
||||
fn () => $dbForPlatform->find('rules', [
|
||||
Query::equal('domain', [$domain->get()]),
|
||||
Query::limit(1)
|
||||
])
|
||||
)[0] ?? new Document();
|
||||
}
|
||||
|
||||
// Skip if verification not needed
|
||||
if ($rule->getAttribute('status', '') !== RULE_STATUS_VERIFICATION_FAILED) {
|
||||
Console::warning('Verification for ' . $rule->getAttribute('domain', '') . ' is not needed.');
|
||||
return;
|
||||
}
|
||||
|
||||
Console::info('Verification for domain ' . $rule->getAttribute('domain', '') . ' started.');
|
||||
|
||||
// Prepare for verification
|
||||
$mainDomain = $this->getMainDomain();
|
||||
$isMainDomain = isset($mainDomain) && $domain->get() === $mainDomain;
|
||||
|
||||
// Verify DNS records
|
||||
$updates = new Document();
|
||||
$success = false;
|
||||
try {
|
||||
$this->validateDomain($rule, $isMainDomain, $log, $verificationDomainAPI, $verificationDomainFunction);
|
||||
$updates
|
||||
->setAttribute('logs', '')
|
||||
->setAttribute('status', RULE_STATUS_GENERATING_CERTIFICATE);
|
||||
|
||||
Console::success('Verification succeeded.');
|
||||
$success = true;
|
||||
} catch (ExtendException $err) {
|
||||
Console::warning('Verification failed: ' . $err->getMessage());
|
||||
$updates->setAttribute('logs', $err->getMessage());
|
||||
}
|
||||
|
||||
$rule = $dbForPlatform->updateDocument('rules', $rule->getId(), $updates);
|
||||
|
||||
// Issue a TLS certificate when domain is verified
|
||||
if ($success) {
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain'),
|
||||
'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')),
|
||||
]))
|
||||
->trigger();
|
||||
|
||||
Console::success('Certificate generation triggered successfully.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,12 +193,13 @@ class Certificates extends Action
|
||||
* @param CertificatesAdapter $certificates
|
||||
* @param bool $skipRenewCheck
|
||||
* @param array $plan
|
||||
* @param string|null $validationDomain
|
||||
* @param ?string $verificationDomainFunction
|
||||
* @param ?string $verificationDomainAPI
|
||||
* @return void
|
||||
* @throws Throwable
|
||||
* @throws \Utopia\Database\Exception
|
||||
*/
|
||||
private function execute(
|
||||
private function executeGeneration(
|
||||
Domain $domain,
|
||||
?string $domainType,
|
||||
Database $dbForPlatform,
|
||||
@@ -132,7 +212,8 @@ class Certificates extends Action
|
||||
CertificatesAdapter $certificates,
|
||||
bool $skipRenewCheck = false,
|
||||
array $plan = [],
|
||||
?string $validationDomain = null
|
||||
?string $verificationDomainFunction = null,
|
||||
?string $verificationDomainAPI = null
|
||||
): void {
|
||||
/**
|
||||
* 1. Read arguments and validate domain
|
||||
@@ -172,17 +253,44 @@ class Certificates extends Action
|
||||
$certificate->setAttribute('domain', $domain->get());
|
||||
}
|
||||
|
||||
$success = false;
|
||||
$status = $certificate->getAttribute('status', RULE_STATUS_GENERATING_CERTIFICATE);
|
||||
|
||||
try {
|
||||
// Clean-up logs from previous attempt
|
||||
if (!empty($certificate->getAttribute('logs', ''))) {
|
||||
$certificate->setAttribute('logs', '');
|
||||
}
|
||||
|
||||
$date = \date('H:i:s');
|
||||
$certificate->setAttribute('logs', "\033[90m[{$date}] \033[97mCertificate generation started. \033[0m\n");
|
||||
|
||||
$certificate = $this->upsertCertificate($domain->get(), $certificate, $dbForPlatform);
|
||||
|
||||
// Validate domain and DNS records. Skip if job is forced
|
||||
if (!$skipRenewCheck) {
|
||||
$mainDomain = $validationDomain ?? $this->getMainDomain();
|
||||
$isMainDomain = !isset($mainDomain) || $domain->get() === $mainDomain;
|
||||
$this->validateDomain($domain, $isMainDomain, $log);
|
||||
$mainDomain = $this->getMainDomain();
|
||||
$isMainDomain = isset($mainDomain) && $domain->get() === $mainDomain;
|
||||
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
|
||||
$rule = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get())));
|
||||
} else {
|
||||
$rule = ValidatorAuthorization::skip(
|
||||
fn () => $dbForPlatform->find('rules', [
|
||||
Query::equal('domain', [$domain->get()]),
|
||||
Query::limit(1)
|
||||
])
|
||||
)[0] ?? new Document();
|
||||
}
|
||||
|
||||
if ($rule->isEmpty()) {
|
||||
$rule = new Document([
|
||||
'domain' => $domain->get(),
|
||||
'type' => 'api'
|
||||
]);
|
||||
}
|
||||
|
||||
$this->validateDomain($rule, $isMainDomain, $log, $verificationDomainAPI, $verificationDomainFunction);
|
||||
|
||||
// If certificate exists already, double-check expiry date. Skip if job is forced
|
||||
if (!$certificates->isRenewRequired($domain->get(), $domainType, $log)) {
|
||||
@@ -195,15 +303,22 @@ class Certificates extends Action
|
||||
$certName = ID::unique();
|
||||
$renewDate = $certificates->issueCertificate($certName, $domain->get(), $domainType);
|
||||
|
||||
// Command succeeded, store all data into document
|
||||
$certificate->setAttribute('logs', 'Certificate successfully generated.');
|
||||
// This is useful when cert provider does extra work in background
|
||||
// For example, verification, or example certificate distribution to all edges
|
||||
if ($certificates->isIssueInstant($domain->get(), $domainType)) {
|
||||
$status = RULE_STATUS_SUCCESSFUL;
|
||||
|
||||
// Command succeeded, store all data into document
|
||||
$certificate->setAttribute('logs', 'Certificate successfully generated.');
|
||||
}
|
||||
|
||||
// Update certificate info stored in database
|
||||
$certificate->setAttribute('renewDate', $renewDate);
|
||||
$certificate->setAttribute('attempts', 0);
|
||||
$certificate->setAttribute('issueDate', DateTime::now());
|
||||
$success = true;
|
||||
} catch (Throwable $e) {
|
||||
$status = RULE_STATUS_GENERATION_FAILED;
|
||||
|
||||
$logs = $e->getMessage();
|
||||
$currentLogs = $certificate->getAttribute('logs', '');
|
||||
$date = \date('H:i:s');
|
||||
@@ -227,7 +342,10 @@ class Certificates extends Action
|
||||
$certificate->setAttribute('updated', DateTime::now());
|
||||
|
||||
// Save all changes we made to certificate document into database
|
||||
$this->saveCertificateDocument($domain->get(), $certificate, $success, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime);
|
||||
$certificate = $this->upsertCertificate($domain->get(), $certificate, $dbForPlatform);
|
||||
|
||||
// Synchronize new status to all rules
|
||||
$this->updateDomainDocuments($certificate->getId(), $domain->get(), $status, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,27 +354,18 @@ class Certificates extends Action
|
||||
*
|
||||
* @param string $domain Domain name that certificate is for
|
||||
* @param Document $certificate Certificate document that we need to save
|
||||
* @param bool $success
|
||||
* @param Database $dbForPlatform Database connection for console
|
||||
* @param Event $queueForEvents
|
||||
* @param Func $queueForFunctions
|
||||
* @param Realtime $queueForRealtime
|
||||
* @return void
|
||||
* @return Document
|
||||
* @throws \Utopia\Database\Exception
|
||||
* @throws Authorization
|
||||
* @throws Conflict
|
||||
* @throws Structure
|
||||
*/
|
||||
private function saveCertificateDocument(
|
||||
private function upsertCertificate(
|
||||
string $domain,
|
||||
Document $certificate,
|
||||
bool $success,
|
||||
Database $dbForPlatform,
|
||||
Event $queueForEvents,
|
||||
Webhook $queueForWebhooks,
|
||||
Func $queueForFunctions,
|
||||
Realtime $queueForRealtime
|
||||
): void {
|
||||
): Document {
|
||||
// Check if update or insert required
|
||||
$certificateDocument = $dbForPlatform->findOne('certificates', [Query::equal('domain', [$domain])]);
|
||||
if (!$certificateDocument->isEmpty()) {
|
||||
@@ -268,8 +377,7 @@ class Certificates extends Action
|
||||
$certificate = $dbForPlatform->createDocument('certificates', $certificate);
|
||||
}
|
||||
|
||||
$certificateId = $certificate->getId();
|
||||
$this->updateDomainDocuments($certificateId, $domain, $success, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime);
|
||||
return $certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,62 +400,18 @@ class Certificates extends Action
|
||||
* - Domain needs to be public and valid (prevents NFT domains that are not supported)
|
||||
* - Domain must have proper DNS record
|
||||
*
|
||||
* @param Domain $domain Domain which we validate
|
||||
* @param Document $rule Rule which we validate
|
||||
* @param bool $isMainDomain In case of master domain, we look for different DNS configurations
|
||||
* @param string|null $verificationDomainAPI Function to verify domain
|
||||
* @param string|null $verificationDomainFunction Function to verify domain
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function validateDomain(Domain $domain, bool $isMainDomain, Log $log): void
|
||||
private function validateDomain(Document $rule, bool $isMainDomain, Log $log, ?string $verificationDomainAPI = null, ?string $verificationDomainFunction = null): void
|
||||
{
|
||||
if (empty($domain->get())) {
|
||||
throw new Exception('Missing certificate domain.');
|
||||
}
|
||||
|
||||
if (!$domain->isKnown() || $domain->isTest()) {
|
||||
throw new Exception('Unknown public suffix for domain.');
|
||||
}
|
||||
|
||||
if (!$isMainDomain) {
|
||||
$validationStart = \microtime(true);
|
||||
|
||||
$validators = [];
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
|
||||
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
|
||||
}
|
||||
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
|
||||
}
|
||||
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
|
||||
}
|
||||
|
||||
// Validate if domain target is properly configured
|
||||
if (empty($validators)) {
|
||||
throw new Exception('At least one of domain targets environment variable must be configured.');
|
||||
}
|
||||
|
||||
// Verify domain with DNS records
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
if (!$validator->isValid($domain->get())) {
|
||||
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
throw new Exception('Failed to verify domain DNS records.');
|
||||
}
|
||||
|
||||
// Ensure CAA won't block certificate issuance
|
||||
if (!empty(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''))) {
|
||||
$validationStart = \microtime(true);
|
||||
$validator = new DNS(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''), Record::TYPE_CAA);
|
||||
if (!$validator->isValid($domain->get())) {
|
||||
$log->addExtra('dnsTimingCaa', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
$error = $validator->getDescription();
|
||||
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
|
||||
throw new Exception('Failed to verify domain DNS records. CAA records do not allow Appwrite\'s certificate issuer.');
|
||||
}
|
||||
}
|
||||
$this->verifyRule($rule, $log, $verificationDomainAPI, $verificationDomainFunction);
|
||||
} else {
|
||||
// Main domain validation
|
||||
// TODO: Would be awesome to check A/AAAA record here. Maybe dry run?
|
||||
@@ -416,14 +480,14 @@ class Certificates extends Action
|
||||
*
|
||||
* @param string $certificateId ID of a new or updated certificate document
|
||||
* @param string $domain Domain that is affected by new certificate
|
||||
* @param bool $success Was certificate generation successful?
|
||||
* @param string $status Status of the certificate generation, can be 'verifying', 'verified' 'unverified'
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function updateDomainDocuments(
|
||||
string $certificateId,
|
||||
string $domain,
|
||||
bool $success,
|
||||
string $status,
|
||||
Database $dbForPlatform,
|
||||
Event $queueForEvents,
|
||||
Webhook $queueForWebhooks,
|
||||
@@ -440,9 +504,14 @@ class Certificates extends Action
|
||||
}
|
||||
|
||||
if (!$rule->isEmpty()) {
|
||||
$rule->setAttribute('certificateId', $certificateId);
|
||||
$rule->setAttribute('status', $success ? 'verified' : 'unverified');
|
||||
$dbForPlatform->updateDocument('rules', $rule->getId(), $rule);
|
||||
$updates = new Document();
|
||||
|
||||
$updates
|
||||
->setAttribute('certificateId', $certificateId)
|
||||
->setAttribute('status', $status)
|
||||
->setAttribute('$updatedAt', DateTime::now());
|
||||
|
||||
$rule = $dbForPlatform->updateDocument('rules', $rule->getId(), $updates);
|
||||
|
||||
$projectId = $rule->getAttribute('projectId');
|
||||
|
||||
|
||||
@@ -84,17 +84,16 @@ class Rule extends Model
|
||||
'example' => 'main',
|
||||
])
|
||||
->addRule('status', [
|
||||
'type' => self::TYPE_ENUM,
|
||||
'description' => 'Domain verification status. Possible values are "created", "verifying", "verified" and "unverified"',
|
||||
'default' => 'created',
|
||||
'example' => 'verified',
|
||||
'enum' => ['created', 'verifying', 'verified', 'unverified'],
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Domain verification status. Possible values are "' . RULE_STATUS_VERIFICATION_FAILED . '", "' . RULE_STATUS_GENERATING_CERTIFICATE . '", "' . RULE_STATUS_SUCCESSFUL . '" and "' . RULE_STATUS_GENERATION_FAILED . '"',
|
||||
'default' => '',
|
||||
'example' => RULE_STATUS_SUCCESSFUL,
|
||||
])
|
||||
->addRule('logs', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Certificate generation logs. This will return an empty string if generation did not run, or succeeded.',
|
||||
'description' => 'Logs from rule verification or certificate generation. Priority: certificate logs if both have values, otherwise whichever is not empty.',
|
||||
'default' => '',
|
||||
'example' => 'HTTP challegne failed.',
|
||||
'example' => 'Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.',
|
||||
])
|
||||
->addRule('renewAt', [
|
||||
'type' => self::TYPE_DATETIME,
|
||||
|
||||
@@ -15,6 +15,36 @@ class ProxyCustomServerTest extends Scope
|
||||
use ProjectCustom;
|
||||
use SideServer;
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
// Cleanup for testRuleVerification test
|
||||
// Required as it uses static domain name
|
||||
$rules = $this->listRules([
|
||||
'queries' => [
|
||||
Query::endsWith('domain', 'webapp.com')->toString(),
|
||||
Query::limit(1000)->toString(),
|
||||
]
|
||||
]);
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
foreach ($rules['body']['rules'] as $rule) {
|
||||
$ruleId = $rule['$id'];
|
||||
$response = $this->deleteRule($ruleId);
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
if ($rules['body']['total'] > 0) {
|
||||
$rules = $this->listRules([
|
||||
'queries' => [
|
||||
Query::endsWith('domain', 'webapp.com')->toString(),
|
||||
Query::limit(1)
|
||||
]
|
||||
]);
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
$this->assertEquals(0, count($rules['body']['rules']));
|
||||
$this->assertEquals(0, $rules['body']['total']);
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreateRule(): void
|
||||
{
|
||||
$domain = \uniqid() . '-api.myapp.com';
|
||||
@@ -56,7 +86,7 @@ class ProxyCustomServerTest extends Scope
|
||||
$domain = \uniqid() . '.com';
|
||||
$rule = $this->createAPIRule($domain);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals('created', $rule['body']['status']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
}
|
||||
|
||||
public function testCreateRuleVcs(): void
|
||||
@@ -359,7 +389,7 @@ class ProxyCustomServerTest extends Scope
|
||||
|
||||
$rule = $this->createAPIRule($domain);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals('verified', $rule['body']['status']);
|
||||
$this->assertEquals(RULE_STATUS_SUCCESSFUL, $rule['body']['status']);
|
||||
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
|
||||
@@ -368,7 +398,7 @@ class ProxyCustomServerTest extends Scope
|
||||
|
||||
$rule = $this->createAPIRule($domain);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals('verified', $rule['body']['status']);
|
||||
$this->assertEquals(RULE_STATUS_SUCCESSFUL, $rule['body']['status']);
|
||||
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
|
||||
@@ -377,7 +407,7 @@ class ProxyCustomServerTest extends Scope
|
||||
|
||||
$rule = $this->createAPIRule($domain);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals('created', $rule['body']['status']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
|
||||
$ruleId = $rule['body']['$id'];
|
||||
|
||||
@@ -540,4 +570,171 @@ class ProxyCustomServerTest extends Scope
|
||||
$this->assertEquals(0, $rules['body']['total']);
|
||||
$this->assertCount(0, $rules['body']['rules']);
|
||||
}
|
||||
|
||||
public function testRuleVerification(): void
|
||||
{
|
||||
|
||||
// 1. Site rule can verify
|
||||
$site = $this->setupSite();
|
||||
$siteId = $site['siteId'];
|
||||
|
||||
$rule = $this->createSiteRule('stage-site.webapp.com', $siteId);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_GENERATING_CERTIFICATE, $rule['body']['status']);
|
||||
$this->assertEmpty($rule['body']['logs']);
|
||||
$this->assertNotEmpty($rule['body']['$id']);
|
||||
$ruleId = $rule['body']['$id'];
|
||||
|
||||
$rule = $this->updateRuleVerification($ruleId);
|
||||
$this->assertEquals(200, $rule['headers']['status-code']);
|
||||
$this->assertEquals($ruleId, $rule['body']['$id']);
|
||||
$this->assertEquals(RULE_STATUS_GENERATING_CERTIFICATE, $rule['body']['status']);
|
||||
$this->assertEmpty($rule['body']['logs']);
|
||||
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
$this->cleanupSite($siteId);
|
||||
|
||||
// 2. Function rule can verify
|
||||
$function = $this->setupFunction();
|
||||
$functionId = $function['functionId'];
|
||||
|
||||
$rule = $this->createFunctionRule('stage-function.webapp.com', $functionId);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_GENERATING_CERTIFICATE, $rule['body']['status']);
|
||||
$this->assertEmpty($rule['body']['logs']);
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
|
||||
$rule = $this->createAPIRule('stage-site.webapp.com');
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
$this->assertStringContainsString('has incorrect CNAME value', $rule['body']['logs']);
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
|
||||
$this->cleanupFunction($functionId);
|
||||
|
||||
// 3. Wrong A record fails to verify
|
||||
$rule = $this->createAPIRule('wrong-a-webapp.com');
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
$this->assertStringContainsString('is missing CNAME record', $rule['body']['logs']);
|
||||
|
||||
$ruleId = $rule['body']['$id'];
|
||||
$rule = $this->updateRuleVerification($ruleId);
|
||||
$this->assertEquals(400, $rule['headers']['status-code']);
|
||||
$this->assertStringContainsString('is missing CNAME record', $rule['body']['message']);
|
||||
|
||||
$rule = $this->getRule($ruleId);
|
||||
$this->assertEquals(200, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
|
||||
$this->cleanupRule($ruleId);
|
||||
|
||||
// 4. Correct A record can verify
|
||||
$rule = $this->createAPIRule('webapp.com');
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_GENERATING_CERTIFICATE, $rule['body']['status']);
|
||||
$this->assertEmpty($rule['body']['logs']);
|
||||
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
|
||||
// 5. Correct CNAME record can verify (no CAA record)
|
||||
$rule = $this->createAPIRule('stage.webapp.com');
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_GENERATING_CERTIFICATE, $rule['body']['status']);
|
||||
$this->assertEmpty($rule['body']['logs']);
|
||||
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
|
||||
// 6. Missing CNAME record fails to verify
|
||||
$rule = $this->createAPIRule('stage-missing-cname.webapp.com');
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
$this->assertStringContainsString('is missing CNAME record', $rule['body']['logs']);
|
||||
|
||||
$ruleId = $rule['body']['$id'];
|
||||
$rule = $this->updateRuleVerification($ruleId);
|
||||
$this->assertEquals(400, $rule['headers']['status-code']);
|
||||
$this->assertStringContainsString('is missing CNAME record', $rule['body']['message']);
|
||||
|
||||
$rule = $this->getRule($ruleId);
|
||||
$this->assertEquals(200, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
|
||||
$this->cleanupRule($ruleId);
|
||||
|
||||
// 7. Wrong CNAME record fails to verify
|
||||
$rule = $this->createAPIRule('stage-wrong-cname.webapp.com');
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
$this->assertStringContainsString('has incorrect CNAME value', $rule['body']['logs']);
|
||||
|
||||
$ruleId = $rule['body']['$id'];
|
||||
$rule = $this->updateRuleVerification($ruleId);
|
||||
$this->assertEquals(400, $rule['headers']['status-code']);
|
||||
$this->assertStringContainsString('has incorrect CNAME value', $rule['body']['message']);
|
||||
|
||||
$rule = $this->getRule($ruleId);
|
||||
$this->assertEquals(200, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
|
||||
$this->cleanupRule($ruleId);
|
||||
|
||||
// 8. Wrong CAA record fails to verify
|
||||
$rule = $this->createAPIRule('stage-wrong-caa.webapp.com');
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
$this->assertStringContainsString('has incorrect CAA value', $rule['body']['logs']);
|
||||
|
||||
$ruleId = $rule['body']['$id'];
|
||||
$rule = $this->updateRuleVerification($ruleId);
|
||||
$this->assertEquals(400, $rule['headers']['status-code']);
|
||||
$this->assertStringContainsString('has incorrect CAA value', $rule['body']['message']);
|
||||
|
||||
$rule = $this->getRule($ruleId);
|
||||
$this->assertEquals(200, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
|
||||
$this->cleanupRule($ruleId);
|
||||
|
||||
// 9. Correct CAA record can verify
|
||||
$rule = $this->createAPIRule('stage-correct-caa.webapp.com');
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_GENERATING_CERTIFICATE, $rule['body']['status']);
|
||||
$this->assertEmpty($rule['body']['logs']);
|
||||
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
}
|
||||
|
||||
public function testUpdateRuleVerificationWithSameDataUpdatesTimestamp(): void
|
||||
{
|
||||
$domain = \uniqid() . '-timestamp-test.webapp.com';
|
||||
$rule = $this->createAPIRule($domain);
|
||||
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $rule['body']['status']);
|
||||
$this->assertNotEmpty($rule['body']['logs']);
|
||||
|
||||
$ruleId = $rule['body']['$id'];
|
||||
$initialUpdatedAt = $rule['body']['$updatedAt'];
|
||||
$initiallogs = $rule['body']['logs'];
|
||||
|
||||
sleep(1);
|
||||
|
||||
$updatedRule = $this->updateRuleVerification($ruleId);
|
||||
|
||||
$this->assertEquals(400, $updatedRule['headers']['status-code']);
|
||||
$this->assertStringContainsString($initiallogs, $updatedRule['body']['message']);
|
||||
|
||||
$ruleAfterUpdate = $this->getRule($ruleId);
|
||||
$this->assertEquals(200, $ruleAfterUpdate['headers']['status-code']);
|
||||
$this->assertEquals(RULE_STATUS_VERIFICATION_FAILED, $ruleAfterUpdate['body']['status']);
|
||||
$this->assertEquals($initiallogs, $ruleAfterUpdate['body']['logs']);
|
||||
$this->assertNotEquals($initialUpdatedAt, $ruleAfterUpdate['body']['$updatedAt']);
|
||||
|
||||
$initialTime = new \DateTime($initialUpdatedAt);
|
||||
$updatedTime = new \DateTime($ruleAfterUpdate['body']['$updatedAt']);
|
||||
$this->assertGreaterThan($initialTime, $updatedTime);
|
||||
|
||||
$this->cleanupRule($ruleId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
# Re-use public resolver to answer unknown queries
|
||||
. {
|
||||
forward . 1.1.1.1
|
||||
}
|
||||
|
||||
# Zones configuration
|
||||
webapp.com {
|
||||
template IN A {
|
||||
match "^webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN A 203.0.0.1"
|
||||
fallthrough
|
||||
}
|
||||
|
||||
template IN CNAME {
|
||||
match "^stage-site\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN CNAME sites.localhost."
|
||||
fallthrough
|
||||
}
|
||||
|
||||
template IN CNAME {
|
||||
match "^stage-function\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN CNAME functions.localhost."
|
||||
fallthrough
|
||||
}
|
||||
|
||||
template IN CNAME {
|
||||
match "^stage\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN CNAME cname.localhost."
|
||||
fallthrough
|
||||
}
|
||||
|
||||
template IN CNAME {
|
||||
match "^stage-wrong-cname\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN CNAME cname-wrong.tests.appwrite.io."
|
||||
fallthrough
|
||||
}
|
||||
|
||||
template IN A {
|
||||
match "^stage-wrong-caa\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN A 203.0.0.1"
|
||||
fallthrough
|
||||
}
|
||||
|
||||
template IN CAA {
|
||||
match "^stage-wrong-caa\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN CAA 0 issue \"unknown-issuer.org\""
|
||||
fallthrough
|
||||
}
|
||||
|
||||
|
||||
template IN A {
|
||||
match "^stage-correct-caa\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN A 203.0.0.1"
|
||||
fallthrough
|
||||
}
|
||||
|
||||
template IN CAA {
|
||||
match "^stage-correct-caa\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN CAA 0 issue \"digicert.com\""
|
||||
fallthrough
|
||||
}
|
||||
|
||||
forward . 1.1.1.1
|
||||
}
|
||||
|
||||
# Zones configuration
|
||||
wrong-a-webapp.com {
|
||||
template IN A {
|
||||
match "^wrong-a-webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN A 203.0.0.5"
|
||||
fallthrough
|
||||
}
|
||||
}
|
||||
@@ -3,98 +3,51 @@
|
||||
namespace Tests\Unit\Network\Validators;
|
||||
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\Tests\Retry;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Utopia\DNS\Message\Record;
|
||||
|
||||
/**
|
||||
* DNS Setup (on Appwrite Labs digital ocean team, network tab):
|
||||
*
|
||||
* certainly.caa.appwrite.org: CAA 0 issue "certainly.com"
|
||||
* certainly-full.caa.appwrite.org: CAA 128 issuewild "certainly.com;account=123456;validationmethods=dns-01"
|
||||
* letsencrypt.certainly.caa.appwrite.org: CAA 0 issue "letsencrypt.org"
|
||||
*/
|
||||
class DNSTest extends TestCase
|
||||
{
|
||||
public function testCNAME(): void
|
||||
public function testSingleDNSServer(): void
|
||||
{
|
||||
$validator = new DNS('appwrite.io', Record::TYPE_CNAME);
|
||||
$this->assertEquals($validator->isValid(''), false);
|
||||
$this->assertEquals($validator->isValid(null), false);
|
||||
$this->assertEquals($validator->isValid(false), false);
|
||||
$this->assertEquals($validator->isValid('cname-unit-test.appwrite.org'), true);
|
||||
$this->assertEquals($validator->isValid('test1.appwrite.org'), false);
|
||||
$validator = new DNS('appwrite.io', Record::TYPE_CNAME, ['8.8.8.8']);
|
||||
|
||||
$this->assertEquals(false, $validator->isValid(''));
|
||||
$this->assertEquals(false, $validator->isValid(null));
|
||||
$this->assertEquals('string', $validator->getType());
|
||||
}
|
||||
|
||||
public function testA(): void
|
||||
public function testMultipleDNSServers(): void
|
||||
{
|
||||
// IPv4 for documentation purposes
|
||||
$validator = new DNS('203.0.113.1', Record::TYPE_A);
|
||||
$this->assertEquals($validator->isValid(''), false);
|
||||
$this->assertEquals($validator->isValid(null), false);
|
||||
$this->assertEquals($validator->isValid(false), false);
|
||||
$this->assertEquals($validator->isValid('a-unit-test.appwrite.org'), true);
|
||||
$this->assertEquals($validator->isValid('test1.appwrite.org'), false);
|
||||
$validator = new DNS('appwrite.io', Record::TYPE_CNAME, ['8.8.8.8', '1.1.1.1']);
|
||||
|
||||
$this->assertEquals(false, $validator->isValid(''));
|
||||
$this->assertEquals(false, $validator->isValid(null));
|
||||
$this->assertEquals('string', $validator->getType());
|
||||
}
|
||||
|
||||
public function testAAAA(): void
|
||||
public function testValidationFailure(): void
|
||||
{
|
||||
// IPv6 for documentation purposes
|
||||
$validator = new DNS('2001:db8::1', Record::TYPE_AAAA);
|
||||
$this->assertEquals($validator->isValid(''), false);
|
||||
$this->assertEquals($validator->isValid(null), false);
|
||||
$this->assertEquals($validator->isValid(false), false);
|
||||
$this->assertEquals($validator->isValid('aaaa-unit-test.appwrite.org'), true);
|
||||
$this->assertEquals($validator->isValid('test1.appwrite.org'), false);
|
||||
$validator = new DNS('invalid-target.example.com', Record::TYPE_CNAME, ['8.8.8.8', '1.1.1.1']);
|
||||
|
||||
$result = $validator->isValid('nonexistent-domain-' . \uniqid() . '.com');
|
||||
|
||||
$this->assertEquals(false, $result);
|
||||
$this->assertIsInt($validator->count);
|
||||
$this->assertIsString($validator->value);
|
||||
$this->assertIsArray($validator->records);
|
||||
$this->assertIsString($validator->getDescription());
|
||||
}
|
||||
|
||||
#[Retry(count: 5)]
|
||||
public function testCAA(): void
|
||||
public function testCoreDNSFailure(): void
|
||||
{
|
||||
$digitalOceanIp = '172.64.52.210'; // ping ns1.digitalocean.com
|
||||
// CoreDNS is configured to return cname.localhost. for stage.webapp.com
|
||||
$validator = new DNS('cname.localhost.', Record::TYPE_CNAME, ['172.16.238.100', '8.8.8.8']);
|
||||
|
||||
$certainly = new DNS('certainly.com', Record::TYPE_CAA, $digitalOceanIp);
|
||||
$letsencrypt = new DNS('letsencrypt.org', Record::TYPE_CAA, $digitalOceanIp);
|
||||
$result = $validator->isValid('stage.webapp.com');
|
||||
$this->assertEquals(false, $result);
|
||||
|
||||
// No CAA record succeeds on main domain & subdomains for any issuer
|
||||
$this->assertEquals($certainly->isValid('caa.appwrite.org'), true);
|
||||
$this->assertEquals($certainly->isValid('sub.caa.appwrite.org'), true);
|
||||
$this->assertEquals($certainly->isValid('sub.sub.caa.appwrite.org'), true);
|
||||
|
||||
$this->assertEquals($letsencrypt->isValid('caa.appwrite.org'), true);
|
||||
$this->assertEquals($letsencrypt->isValid('sub.caa.appwrite.org'), true);
|
||||
$this->assertEquals($letsencrypt->isValid('sub.sub.caa.appwrite.org'), true);
|
||||
|
||||
// Custom flags and tag is allowed, but only for Certainly
|
||||
$this->assertEquals($certainly->isValid('certainly-full.caa.appwrite.org'), true);
|
||||
$this->assertEquals($letsencrypt->isValid('certainly-full.caa.appwrite.org'), false);
|
||||
|
||||
// Custom flags&tag are not allowed if validator includes specific flags&tag
|
||||
$certainlyFull = new DNS('0 issue "certainly.com"', Record::TYPE_CAA);
|
||||
$this->assertEquals($certainlyFull->isValid('certainly-full.caa.appwrite.org'), false);
|
||||
|
||||
// Custom flags&tag still allows if they match exactly
|
||||
$certainlyFull = new DNS('128 issuewild "certainly.com;account=123456;validationmethods=dns-01"', Record::TYPE_CAA);
|
||||
$this->assertEquals($certainlyFull->isValid('certainly-full.caa.appwrite.org'), true);
|
||||
|
||||
// Certainly CAA allows Certainly, but not LetsEncrypt; Same for subdomains
|
||||
$this->assertEquals($certainly->isValid('certainly.caa.appwrite.org'), true);
|
||||
$this->assertEquals($letsencrypt->isValid('certainly.caa.appwrite.org'), false);
|
||||
|
||||
$this->assertEquals($certainly->isValid('sub.certainly.caa.appwrite.org'), true);
|
||||
$this->assertEquals($letsencrypt->isValid('sub.certainly.caa.appwrite.org'), false);
|
||||
|
||||
$this->assertEquals($certainly->isValid('sub.sub.certainly.caa.appwrite.org'), true);
|
||||
$this->assertEquals($letsencrypt->isValid('sub.sub.certainly.caa.appwrite.org'), false);
|
||||
|
||||
// LetsEncrypt CAA on subdomain with parent allowing Certainly. Only LetsEncrypt is allowed; Same for subdomains
|
||||
$this->assertEquals($certainly->isValid('letsencrypt.certainly.caa.appwrite.org'), false);
|
||||
$this->assertEquals($letsencrypt->isValid('letsencrypt.certainly.caa.appwrite.org'), true);
|
||||
|
||||
$this->assertEquals($certainly->isValid('sub.letsencrypt.certainly.caa.appwrite.org'), false);
|
||||
$this->assertEquals($letsencrypt->isValid('sub.letsencrypt.certainly.caa.appwrite.org'), true);
|
||||
|
||||
$this->assertEquals($certainly->isValid('sub.sub.letsencrypt.certainly.caa.appwrite.org'), false);
|
||||
$this->assertEquals($letsencrypt->isValid('sub.sub.letsencrypt.certainly.caa.appwrite.org'), true);
|
||||
$result = $validator->isValid('stage-wrong-cname.webapp.com');
|
||||
$this->assertEquals(false, $result);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user