mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '1.8.x' of https://github.com/appwrite/appwrite into joins2
This commit is contained in:
@@ -26,7 +26,7 @@ _APP_DNS=172.16.238.100 # CoreDNS
|
||||
_APP_DOMAIN=appwrite.test
|
||||
_APP_CONSOLE_DOMAIN=localhost
|
||||
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
||||
_APP_DOMAIN_SITES=sites.localhost
|
||||
_APP_DOMAIN_SITES=sites.localhost,rebranded.localhost
|
||||
_APP_DOMAIN_TARGET_CNAME=cname.localhost
|
||||
_APP_DOMAIN_TARGET_A=203.0.0.1
|
||||
_APP_DOMAIN_TARGET_AAAA=::1
|
||||
|
||||
@@ -44,6 +44,7 @@ Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false));
|
||||
// require controllers after overwriting runtimes
|
||||
require_once __DIR__ . '/controllers/general.php';
|
||||
|
||||
global $register;
|
||||
CLI::setResource('register', fn () => $register);
|
||||
|
||||
CLI::setResource('cache', function ($pools) {
|
||||
|
||||
+13
-1
@@ -2,6 +2,17 @@
|
||||
|
||||
use Utopia\System\System;
|
||||
|
||||
// For now, take first domain as primary (for previews)
|
||||
// Later-on this can become platform-specific with new env var (appwrite=this,imagine=that)
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
if (\str_contains($sitesDomain, ',')) {
|
||||
$sitesDomain = explode(',', $sitesDomain)[0];
|
||||
}
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
if (\str_contains($functionsDomain, ',')) {
|
||||
$functionsDomain = explode(',', $functionsDomain)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Platform configuration
|
||||
*/
|
||||
@@ -23,5 +34,6 @@ return [
|
||||
'privacyUrl' => APP_EMAIL_PRIVACY_URL,
|
||||
'websiteUrl' => 'https://' . APP_DOMAIN,
|
||||
'emailSenderName' => APP_EMAIL_PLATFORM_NAME,
|
||||
'sitePreviewDomain' => System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
'sitesDomain' => $sitesDomain,
|
||||
'functionsDomain' => $functionsDomain,
|
||||
];
|
||||
|
||||
@@ -339,7 +339,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
$projectId = $project->getId();
|
||||
|
||||
// Deployment preview
|
||||
$sitesDomain = $platform['sitePreviewDomain'];
|
||||
$sitesDomain = $platform['sitesDomain'];
|
||||
$domain = ID::unique() . "." . $sitesDomain;
|
||||
$ruleId = md5($domain);
|
||||
$previewRuleId = $ruleId;
|
||||
|
||||
+41
-22
@@ -86,22 +86,32 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
|
||||
if ($rule->isEmpty()) {
|
||||
$appDomainFunctionsFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
|
||||
$appDomainFunctions = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
$appDomainSites = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
if (!empty($appDomainFunctionsFallback) && \str_ends_with($host, $appDomainFunctionsFallback)) {
|
||||
$appDomainFunctions = $appDomainFunctionsFallback;
|
||||
$denyDomains = [];
|
||||
$denyEnvVars = [
|
||||
System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''),
|
||||
System::getEnv('_APP_DOMAIN_FUNCTIONS', ''),
|
||||
System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
];
|
||||
foreach ($denyEnvVars as $denyEnvVar) {
|
||||
foreach (\explode(',', $denyEnvVar) as $denyDomain) {
|
||||
if (empty($denyDomain)) {
|
||||
continue;
|
||||
}
|
||||
$denyDomains[] = $denyDomain;
|
||||
}
|
||||
}
|
||||
|
||||
if ($host === $appDomainFunctions || $host === $appDomainSites) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.', view: $errorView);
|
||||
}
|
||||
foreach ($denyDomains as $denyDomain) {
|
||||
if ($host === $denyDomain) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.', view: $errorView);
|
||||
}
|
||||
|
||||
if (\str_ends_with($host, $appDomainFunctions) || \str_ends_with($host, $appDomainSites)) {
|
||||
$exception = new AppwriteException(AppwriteException::RULE_NOT_FOUND, 'This domain is not connected to any Appwrite resources. Visit domains tab under function/site settings to configure it.', view: $errorView);
|
||||
if (\str_ends_with($host, $denyDomain)) {
|
||||
$exception = new AppwriteException(AppwriteException::RULE_NOT_FOUND, 'This domain is not connected to any Appwrite resources. Visit domains tab under function/site settings to configure it.', view: $errorView);
|
||||
|
||||
$exception->addCTA('Start with this domain', $url . '/console');
|
||||
throw $exception;
|
||||
$exception->addCTA('Start with this domain', $url . '/console');
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($host, $platformHostnames)) {
|
||||
@@ -1098,19 +1108,28 @@ App::init()
|
||||
|
||||
// 5. Create new rule
|
||||
$owner = '';
|
||||
$fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
|
||||
$funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
$siteDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
|
||||
if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) {
|
||||
$funcDomain = $fallback;
|
||||
// Mark owner as Appwrite if its appwrite-owned domain
|
||||
$appwriteDomains = [];
|
||||
$appwriteDomainEnvs = [
|
||||
System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''),
|
||||
System::getEnv('_APP_DOMAIN_FUNCTIONS', ''),
|
||||
System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
];
|
||||
foreach ($appwriteDomainEnvs as $appwriteDomainEnv) {
|
||||
foreach (\explode(',', $appwriteDomainEnv) as $appwriteDomain) {
|
||||
if (empty($appwriteDomain)) {
|
||||
continue;
|
||||
}
|
||||
$appwriteDomains[] = $appwriteDomain;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) ||
|
||||
(!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain))
|
||||
) {
|
||||
$owner = 'Appwrite';
|
||||
foreach ($appwriteDomains as $appwriteDomain) {
|
||||
if (\str_ends_with($domain->get(), $appwriteDomain)) {
|
||||
$owner = 'Appwrite';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$ruleId = $isMd5 ? md5($domain->get()) : ID::unique();
|
||||
|
||||
+35
-3
@@ -100,11 +100,19 @@ function dispatch(Server $server, int $fd, int $type, $data = null): int
|
||||
$risky = false;
|
||||
if (str_starts_with($request, 'POST') && str_contains($request, '/executions')) {
|
||||
$risky = true;
|
||||
} elseif (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS'))) {
|
||||
$risky = true;
|
||||
} elseif ($domains->get(md5($domain), 'value') === 1) {
|
||||
// executions request coming from custom domain
|
||||
$risky = true;
|
||||
} else {
|
||||
foreach (\explode(',', System::getEnv('_APP_DOMAIN_FUNCTIONS')) as $riskyDomain) {
|
||||
if (empty($riskyDomain)) {
|
||||
continue;
|
||||
}
|
||||
if (str_ends_with($domain, $riskyDomain)) {
|
||||
$risky = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($risky) {
|
||||
@@ -591,9 +599,33 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
||||
$sum = count($results);
|
||||
foreach ($results as $document) {
|
||||
$domain = $document->getAttribute('domain');
|
||||
if (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS')) || str_ends_with($domain, System::getEnv('_APP_DOMAIN_SITES'))) {
|
||||
|
||||
$denyDomains = [];
|
||||
$denyEnvVars = [
|
||||
System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''),
|
||||
System::getEnv('_APP_DOMAIN_FUNCTIONS', ''),
|
||||
System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
];
|
||||
foreach ($denyEnvVars as $denyEnvVar) {
|
||||
foreach (\explode(',', $denyEnvVar) as $denyDomain) {
|
||||
if (empty($denyDomain)) {
|
||||
continue;
|
||||
}
|
||||
$denyDomains[] = $denyDomain;
|
||||
}
|
||||
}
|
||||
|
||||
$isDenyDomain = false;
|
||||
foreach ($denyDomains as $denyDomain) {
|
||||
if (str_ends_with($domain, $denyDomain)) {
|
||||
$isDenyDomain = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isDenyDomain) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$domains->set(md5($domain), ['value' => 1]);
|
||||
}
|
||||
$latestDocument = !empty(array_key_last($results)) ? $results[array_key_last($results)] : null;
|
||||
|
||||
@@ -10,7 +10,7 @@ class Exception extends AppwriteException
|
||||
protected string $error = '';
|
||||
protected string $errorDescription = '';
|
||||
|
||||
public function __construct(string $response = '', int $code = 0, \Throwable $previous = null)
|
||||
public function __construct(string $response = '', int $code = 0, ?\Throwable $previous = null)
|
||||
{
|
||||
$this->response = $response;
|
||||
$this->message = $response;
|
||||
|
||||
@@ -23,6 +23,7 @@ class Event
|
||||
|
||||
public const FUNCTIONS_QUEUE_NAME = 'v1-functions';
|
||||
public const FUNCTIONS_CLASS_NAME = 'FunctionsV1';
|
||||
public const FUNCTIONS_QUEUE_TTL = 60 * 60 * 24 * 7; // 7 days
|
||||
|
||||
public const STATS_RESOURCES_QUEUE_NAME = 'v1-stats-resources';
|
||||
public const STATS_RESOURCES_CLASS_NAME = 'StatsResourcesV1';
|
||||
@@ -65,6 +66,8 @@ class Event
|
||||
/** @var bool Non-critical events will not throw an exception when enqueuing of the event fails. */
|
||||
protected bool $critical = true;
|
||||
|
||||
protected int $ttl = 0;
|
||||
|
||||
/**
|
||||
* @param Publisher $publisher
|
||||
* @return void
|
||||
@@ -114,6 +117,29 @@ class Event
|
||||
return $this->queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TTL (time-to-live) for jobs in this queue.
|
||||
*
|
||||
* @param int $ttl TTL in seconds
|
||||
* @return static
|
||||
*/
|
||||
public function setTTL(int $ttl): static
|
||||
{
|
||||
$this->ttl = $ttl;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TTL (time-to-live) for jobs in this queue.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTTL(): int
|
||||
{
|
||||
return $this->ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set event name used for this event.
|
||||
* @param string $event
|
||||
@@ -369,7 +395,7 @@ class Event
|
||||
}
|
||||
|
||||
/** The getter is required since events like Databases need to override the queue name depending on the project */
|
||||
$queue = new Queue($this->getQueue());
|
||||
$queue = new Queue($this->getQueue(), 'utopia-queue', $this->getTTL());
|
||||
|
||||
// Merge the base payload with any trimmed values
|
||||
$payload = array_merge($this->preparePayload(), $this->trimPayload());
|
||||
|
||||
@@ -27,7 +27,8 @@ class Func extends Event
|
||||
|
||||
$this
|
||||
->setQueue(System::getEnv('_APP_FUNCTIONS_QUEUE_NAME', Event::FUNCTIONS_QUEUE_NAME))
|
||||
->setClass(System::getEnv('_APP_FUNCTIONS_CLASS_NAME', Event::FUNCTIONS_CLASS_NAME));
|
||||
->setClass(System::getEnv('_APP_FUNCTIONS_CLASS_NAME', Event::FUNCTIONS_CLASS_NAME))
|
||||
->setTTL(Event::FUNCTIONS_QUEUE_TTL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -392,9 +392,9 @@ class Exception extends \Exception
|
||||
|
||||
public function __construct(
|
||||
string $type = Exception::GENERAL_UNKNOWN,
|
||||
string $message = null,
|
||||
int|string $code = null,
|
||||
\Throwable $previous = null,
|
||||
?string $message = null,
|
||||
int|string|null $code = null,
|
||||
?\Throwable $previous = null,
|
||||
?string $view = null,
|
||||
array $params = []
|
||||
) {
|
||||
|
||||
@@ -297,7 +297,7 @@ class Realtime extends MessagingAdapter
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $collection = null, Document $bucket = null): array
|
||||
public static function fromPayload(string $event, Document $payload, ?Document $project = null, ?Document $database = null, ?Document $collection = null, ?Document $bucket = null): array
|
||||
{
|
||||
$channels = [];
|
||||
$roles = [];
|
||||
|
||||
@@ -211,7 +211,7 @@ abstract class Migration
|
||||
* @return void
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function createCollection(string $id, string $name = null): void
|
||||
protected function createCollection(string $id, ?string $name = null): void
|
||||
{
|
||||
$name ??= $id;
|
||||
|
||||
@@ -262,7 +262,7 @@ abstract class Migration
|
||||
Database $database,
|
||||
string $collectionId,
|
||||
array $attributeIds,
|
||||
string $from = null
|
||||
?string $from = null
|
||||
): void {
|
||||
$from ??= $collectionId;
|
||||
|
||||
@@ -327,7 +327,7 @@ abstract class Migration
|
||||
Database $database,
|
||||
string $collectionId,
|
||||
string $attributeId,
|
||||
string $from = null
|
||||
?string $from = null
|
||||
): void {
|
||||
$from ??= $collectionId;
|
||||
|
||||
@@ -385,7 +385,7 @@ abstract class Migration
|
||||
* @throws Duplicate
|
||||
* @throws Limit
|
||||
*/
|
||||
public function createIndexFromCollection(Database $database, string $collectionId, string $indexId, string $from = null): void
|
||||
public function createIndexFromCollection(Database $database, string $collectionId, string $indexId, ?string $from = null): void
|
||||
{
|
||||
$from ??= $collectionId;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class Action extends UtopiaAction
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function foreachDocument(Database $database, string $collection, array $queries = [], callable $callback = null, int $limit = 1000, bool $concurrent = false): void
|
||||
protected function foreachDocument(Database $database, string $collection, array $queries = [], ?callable $callback = null, int $limit = 1000, bool $concurrent = false): void
|
||||
{
|
||||
$results = [];
|
||||
$sum = $limit;
|
||||
|
||||
@@ -144,7 +144,7 @@ class Base extends Action
|
||||
return $deployment;
|
||||
}
|
||||
|
||||
public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, Authorization $authorization, string $referenceType = 'branch', string $reference = '', array $platform): Document
|
||||
public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, Authorization $authorization, array $platform, string $referenceType = 'branch', string $reference = ''): Document
|
||||
{
|
||||
$deploymentId = ID::unique();
|
||||
$providerInstallationId = $installation->getAttribute('providerInstallationId', '');
|
||||
@@ -235,7 +235,7 @@ class Base extends Action
|
||||
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
|
||||
$dbForProject->updateDocument('sites', $site->getId(), $site);
|
||||
|
||||
$sitesDomain = $platform['sitePreviewDomain'];
|
||||
$sitesDomain = $platform['sitesDomain'];
|
||||
$domain = ID::unique() . "." . $sitesDomain;
|
||||
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
|
||||
@@ -74,36 +74,41 @@ class Get extends Action
|
||||
) {
|
||||
$domains = $platform['hostnames'] ?? [];
|
||||
if ($type === 'rules') {
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$deniedDomains = [...$domains];
|
||||
$restrictions = [];
|
||||
if (!empty($sitesDomain)) {
|
||||
|
||||
$sitesDomains = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
foreach (\explode(',', $sitesDomains) as $sitesDomain) {
|
||||
if (empty($sitesDomain)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
|
||||
// Ensure site domains are exactly 1 subdomain, and dont start with reserved prefix
|
||||
$domainLevel = \count(\explode('.', $sitesDomain));
|
||||
$restrictions[] = DomainValidator::createRestriction($sitesDomain, $domainLevel + 1, ['commit-', 'branch-']);
|
||||
}
|
||||
if (!empty($functionsDomain)) {
|
||||
|
||||
$functionsDomains = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
foreach (\explode(',', $functionsDomains) as $functionsDomain) {
|
||||
if (empty($functionsDomain)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
|
||||
// Ensure function domains are exactly 1 subdomain
|
||||
$domainLevel = \count(\explode('.', $functionsDomain));
|
||||
$restrictions[] = DomainValidator::createRestriction($functionsDomain, $domainLevel + 1);
|
||||
}
|
||||
|
||||
$validator = new DomainValidator($restrictions);
|
||||
|
||||
if (!$validator->isValid($value)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
$deniedDomains = [...$domains];
|
||||
|
||||
if (!empty($sitesDomain)) {
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
}
|
||||
|
||||
if (!empty($functionsDomain)) {
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
}
|
||||
|
||||
$denyListDomains = System::getEnv('_APP_CUSTOM_DOMAIN_DENY_LIST', '');
|
||||
$denyListDomains = \array_map('trim', explode(',', $denyListDomains));
|
||||
foreach ($denyListDomains as $denyListDomain) {
|
||||
|
||||
@@ -46,10 +46,11 @@ class Get extends Action
|
||||
contentType: ContentType::JSON
|
||||
))
|
||||
->inject('response')
|
||||
->inject('platform')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(Response $response)
|
||||
public function action(Response $response, array $platform)
|
||||
{
|
||||
$validator = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME'));
|
||||
$isCNAMEValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')) && $validator->isKnown() && !$validator->isTest();
|
||||
@@ -82,8 +83,8 @@ class Get extends Action
|
||||
'_APP_VCS_ENABLED' => $isVcsEnabled,
|
||||
'_APP_DOMAIN_ENABLED' => $isDomainEnabled,
|
||||
'_APP_ASSISTANT_ENABLED' => $isAssistantEnabled,
|
||||
'_APP_DOMAIN_SITES' => System::getEnv('_APP_DOMAIN_SITES'),
|
||||
'_APP_DOMAIN_FUNCTIONS' => System::getEnv('_APP_DOMAIN_FUNCTIONS'),
|
||||
'_APP_DOMAIN_SITES' => $platform['sitesDomain'],
|
||||
'_APP_DOMAIN_FUNCTIONS' => $platform['functionsDomain'],
|
||||
'_APP_OPTIONS_FORCE_HTTPS' => System::getEnv('_APP_OPTIONS_FORCE_HTTPS'),
|
||||
'_APP_DOMAINS_NAMESERVERS' => System::getEnv('_APP_DOMAINS_NAMESERVERS'),
|
||||
]);
|
||||
|
||||
+1
-1
@@ -488,7 +488,7 @@ abstract class Action extends UtopiaAction
|
||||
return $attribute;
|
||||
}
|
||||
|
||||
protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, Authorization $authorization, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document
|
||||
protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, Authorization $authorization, string $type, ?int $size = null, ?string $filter = null, string|bool|int|float|array|null $default = null, ?bool $required = null, int|float|null $min = null, int|float|null $max = null, ?array $elements = null, array $options = [], ?string $newKey = null): Document
|
||||
{
|
||||
$db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
|
||||
@@ -578,7 +578,7 @@ class Databases extends Action
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteByGroup(string $collectionId, array $queries, Database $database, callable $callback = null): void
|
||||
protected function deleteByGroup(string $collectionId, array $queries, Database $database, ?callable $callback = null): void
|
||||
{
|
||||
$start = \microtime(true);
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ class Create extends Base
|
||||
->inject('request')
|
||||
->inject('gitHub')
|
||||
->inject('authorization')
|
||||
->inject('platform')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -154,7 +155,8 @@ class Create extends Base
|
||||
Database $dbForPlatform,
|
||||
Request $request,
|
||||
GitHub $github,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
array $platform
|
||||
) {
|
||||
|
||||
// Temporary abuse check
|
||||
@@ -321,7 +323,6 @@ class Create extends Base
|
||||
template: $template,
|
||||
github: $github,
|
||||
activate: true,
|
||||
authorization: $authorization,
|
||||
reference: $providerBranch,
|
||||
referenceType: 'branch'
|
||||
);
|
||||
@@ -366,7 +367,7 @@ class Create extends Base
|
||||
->setTemplate($template);
|
||||
}
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
$functionsDomain = $platform['functionsDomain'];
|
||||
if (!empty($functionsDomain)) {
|
||||
$routeSubdomain = ID::unique();
|
||||
$domain = "{$routeSubdomain}.{$functionsDomain}";
|
||||
|
||||
@@ -1037,7 +1037,7 @@ class Builds extends Action
|
||||
// VCS branch
|
||||
$branchName = $deployment->getAttribute('providerBranch');
|
||||
if (!empty($branchName)) {
|
||||
$sitesDomain = $platform['sitePreviewDomain'];
|
||||
$sitesDomain = $platform['sitesDomain'];
|
||||
$branchPrefix = substr($branchName, 0, 16);
|
||||
if (strlen($branchName) > 16) {
|
||||
$remainingChars = substr($branchName, 16);
|
||||
|
||||
@@ -31,34 +31,42 @@ class Action extends PlatformAction
|
||||
protected function validateDomainRestrictions(string $domain, array $platform): void
|
||||
{
|
||||
$domains = $platform['hostnames'] ?? [];
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$deniedDomains = [...$domains];
|
||||
$restrictions = [];
|
||||
if (!empty($sitesDomain)) {
|
||||
|
||||
$sitesDomains = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
foreach (\explode(',', $sitesDomains) as $sitesDomain) {
|
||||
if (empty($sitesDomain)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
|
||||
// Ensure site domains are exactly 1 subdomain, and dont start with reserved prefix
|
||||
$domainLevel = \count(\explode('.', $sitesDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($sitesDomain, $domainLevel + 1, ['commit-', 'branch-']);
|
||||
}
|
||||
if (!empty($functionsDomain)) {
|
||||
|
||||
$functionsDomains = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
foreach (\explode(',', $functionsDomains) as $functionsDomain) {
|
||||
if (empty($functionsDomains)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
|
||||
// Ensure function domains are exactly 1 subdomain
|
||||
$domainLevel = \count(\explode('.', $functionsDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($functionsDomain, $domainLevel + 1);
|
||||
}
|
||||
|
||||
$validator = new ValidatorDomain($restrictions);
|
||||
|
||||
if (!$validator->isValid($domain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
$deniedDomains = [...$domains];
|
||||
|
||||
if (!empty($sitesDomain)) {
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
}
|
||||
|
||||
if (!empty($functionsDomain)) {
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
}
|
||||
|
||||
$denyListDomains = System::getEnv('_APP_CUSTOM_DOMAIN_DENY_LIST', '');
|
||||
$denyListDomains = \array_map('trim', explode(',', $denyListDomains));
|
||||
foreach ($denyListDomains as $denyListDomain) {
|
||||
@@ -117,31 +125,51 @@ class Action extends PlatformAction
|
||||
}
|
||||
}
|
||||
|
||||
$targetCNAME = null;
|
||||
$targetCNAMEs = [];
|
||||
$ruleType = $rule->getAttribute('type', '');
|
||||
$resourceType = $rule->getAttribute('deploymentResourceType', '');
|
||||
|
||||
// Ensures different target based on rule's type, as configured by env variables
|
||||
if ($resourceType === 'function') {
|
||||
// For example: fra.appwrite.run
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_FUNCTIONS', ''));
|
||||
foreach (\explode(',', System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) as $targetCNAME) {
|
||||
if (empty($targetCNAME)) {
|
||||
continue;
|
||||
}
|
||||
$targetCNAMEs[] = new Domain($targetCNAME);
|
||||
}
|
||||
} elseif ($resourceType === 'site') {
|
||||
// For example: appwrite.network
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', ''));
|
||||
foreach (\explode(',', System::getEnv('_APP_DOMAIN_SITES', '')) as $targetCNAME) {
|
||||
if (empty($targetCNAME)) {
|
||||
continue;
|
||||
}
|
||||
$targetCNAMEs[] = new Domain($targetCNAME);
|
||||
}
|
||||
} elseif ($ruleType === 'api') {
|
||||
// For example: fra.cloud.appwrite.io
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
$targetCNAMEs[] = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
} elseif ($ruleType === 'redirect') {
|
||||
// Shouldn't be needed, because redirect should always have resourceTyp too, but just in case we default to sites
|
||||
// For example: appwrite.network
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', ''));
|
||||
foreach (\explode(',', System::getEnv('_APP_DOMAIN_SITES', '')) as $targetCNAME) {
|
||||
if (empty($targetCNAME)) {
|
||||
continue;
|
||||
}
|
||||
$targetCNAMEs[] = new Domain($targetCNAME);
|
||||
}
|
||||
}
|
||||
|
||||
$validators = [];
|
||||
$mainValidator = null; // Validator to use for error description
|
||||
|
||||
if (!is_null($targetCNAME)) {
|
||||
$validator = new $dnsValidatorClass($targetCNAME->get(), Record::TYPE_CNAME, $dnsServers);
|
||||
if (\count($targetCNAMEs) > 0) {
|
||||
$cnameValidators = [];
|
||||
foreach ($targetCNAMEs as $targetCNAME) {
|
||||
$cnameValidators[] = new $dnsValidatorClass($targetCNAME->get(), Record::TYPE_CNAME, $dnsServers);
|
||||
}
|
||||
|
||||
$validator = new AnyOf($cnameValidators);
|
||||
$validators[] = $validator;
|
||||
|
||||
if (\is_null($mainValidator)) {
|
||||
@@ -185,4 +213,30 @@ class Action extends PlatformAction
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED, $mainValidator->getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
protected function isAppwriteOwned(string $domain): bool
|
||||
{
|
||||
$appwriteDomains = [];
|
||||
$appwriteDomainEnvs = [
|
||||
System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''),
|
||||
System::getEnv('_APP_DOMAIN_FUNCTIONS', ''),
|
||||
System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
];
|
||||
foreach ($appwriteDomainEnvs as $appwriteDomainEnv) {
|
||||
foreach (\explode(',', $appwriteDomainEnv) as $appwriteDomain) {
|
||||
if (empty($appwriteDomain)) {
|
||||
continue;
|
||||
}
|
||||
$appwriteDomains[] = $appwriteDomain;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($appwriteDomains as $appwriteDomain) {
|
||||
if (\str_ends_with($domain, $appwriteDomain)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,18 +74,12 @@ class Create extends Action
|
||||
{
|
||||
$this->validateDomainRestrictions($domain, $platform);
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique();
|
||||
$status = RULE_STATUS_CREATED;
|
||||
$owner = '';
|
||||
|
||||
if (
|
||||
($functionsDomain != '' && \str_ends_with($domain, $functionsDomain)) ||
|
||||
($sitesDomain != '' && \str_ends_with($domain, $sitesDomain))
|
||||
) {
|
||||
if ($this->isAppwriteOwned($domain)) {
|
||||
$status = RULE_STATUS_VERIFIED;
|
||||
$owner = 'Appwrite';
|
||||
}
|
||||
|
||||
@@ -79,9 +79,6 @@ class Create extends Action
|
||||
{
|
||||
$this->validateDomainRestrictions($domain, $platform);
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND);
|
||||
@@ -94,10 +91,7 @@ class Create extends Action
|
||||
$status = RULE_STATUS_CREATED;
|
||||
$owner = '';
|
||||
|
||||
if (
|
||||
($functionsDomain != '' && \str_ends_with($domain, $functionsDomain)) ||
|
||||
($sitesDomain != '' && \str_ends_with($domain, $sitesDomain))
|
||||
) {
|
||||
if ($this->isAppwriteOwned($domain)) {
|
||||
$status = RULE_STATUS_VERIFIED;
|
||||
$owner = 'Appwrite';
|
||||
}
|
||||
|
||||
@@ -82,9 +82,6 @@ class Create extends Action
|
||||
{
|
||||
$this->validateDomainRestrictions($domain, $platform);
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$collection = match ($resourceType) {
|
||||
'site' => 'sites',
|
||||
'function' => 'functions'
|
||||
@@ -99,10 +96,7 @@ class Create extends Action
|
||||
$status = RULE_STATUS_CREATED;
|
||||
$owner = '';
|
||||
|
||||
if (
|
||||
($functionsDomain != '' && \str_ends_with($domain, $functionsDomain)) ||
|
||||
($sitesDomain != '' && \str_ends_with($domain, $sitesDomain))
|
||||
) {
|
||||
if ($this->isAppwriteOwned($domain)) {
|
||||
$status = RULE_STATUS_VERIFIED;
|
||||
$owner = 'Appwrite';
|
||||
}
|
||||
|
||||
@@ -79,9 +79,6 @@ class Create extends Action
|
||||
{
|
||||
$this->validateDomainRestrictions($domain, $platform);
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
if ($site->isEmpty()) {
|
||||
throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND);
|
||||
@@ -94,10 +91,7 @@ class Create extends Action
|
||||
$status = RULE_STATUS_CREATED;
|
||||
$owner = '';
|
||||
|
||||
if (
|
||||
($functionsDomain != '' && \str_ends_with($domain, $functionsDomain)) ||
|
||||
($sitesDomain != '' && \str_ends_with($domain, $sitesDomain))
|
||||
) {
|
||||
if ($this->isAppwriteOwned($domain)) {
|
||||
$status = RULE_STATUS_VERIFIED;
|
||||
$owner = 'Appwrite';
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ class Create extends Action
|
||||
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
|
||||
$dbForProject->updateDocument('sites', $site->getId(), $site);
|
||||
|
||||
$sitesDomain = $platform['sitePreviewDomain'];
|
||||
$sitesDomain = $platform['sitesDomain'];
|
||||
$domain = ID::unique() . "." . $sitesDomain;
|
||||
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
@@ -344,7 +344,7 @@ class Create extends Action
|
||||
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
|
||||
$dbForProject->updateDocument('sites', $site->getId(), $site);
|
||||
|
||||
$sitesDomain = $platform['sitePreviewDomain'];
|
||||
$sitesDomain = $platform['sitesDomain'];
|
||||
$domain = ID::unique() . "." . $sitesDomain;
|
||||
$ruleId = md5($domain);
|
||||
$authorization->skip(
|
||||
|
||||
@@ -145,7 +145,7 @@ class Create extends Action
|
||||
$dbForProject->updateDocument('sites', $site->getId(), $site);
|
||||
|
||||
// Preview deployments for sites
|
||||
$sitesDomain = $platform['sitePreviewDomain'];
|
||||
$sitesDomain = $platform['sitesDomain'];
|
||||
$domain = ID::unique() . "." . $sitesDomain;
|
||||
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
|
||||
@@ -189,7 +189,7 @@ class Create extends Base
|
||||
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
|
||||
$dbForProject->updateDocument('sites', $site->getId(), $site);
|
||||
|
||||
$sitesDomain = $platform['sitePreviewDomain'];
|
||||
$sitesDomain = $platform['sitesDomain'];
|
||||
$domain = ID::unique() . "." . $sitesDomain;
|
||||
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
|
||||
@@ -84,13 +84,6 @@ class Interval extends Action
|
||||
$this->verifyDomain($dbForPlatform, $queueForCertificates);
|
||||
},
|
||||
'interval' => $intervalDomainVerification * 1000,
|
||||
],
|
||||
[
|
||||
'name' => 'cleanupStaleExecutions',
|
||||
'callback' => function (Database $dbForPlatform, callable $getProjectDB, Certificate $queueForCertificates) {
|
||||
$this->cleanupStaleExecutions($dbForPlatform, $getProjectDB);
|
||||
},
|
||||
'interval' => $intervalCleanupStaleExecutions * 1000,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ use Utopia\Database\Exception\Conflict;
|
||||
use Utopia\Database\Exception\Restricted;
|
||||
use Utopia\Database\Exception\Structure;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Action;
|
||||
@@ -335,7 +336,7 @@ class Deletes extends Action
|
||||
* @throws Authorization
|
||||
* @throws Exception
|
||||
*/
|
||||
private function deleteCacheByResource(Document $project, callable $getProjectDB, string $resource, string $resourceType = null): void
|
||||
private function deleteCacheByResource(Document $project, callable $getProjectDB, string $resource, ?string $resourceType = null): void
|
||||
{
|
||||
$projectId = $project->getId();
|
||||
$dbForProject = $getProjectDB($project);
|
||||
@@ -1370,7 +1371,7 @@ class Deletes extends Action
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function listByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
|
||||
protected function listByGroup(string $collection, array $queries, Database $database, ?callable $callback = null): void
|
||||
{
|
||||
$count = 0;
|
||||
$limit = 1000;
|
||||
|
||||
@@ -273,8 +273,8 @@ class Functions extends Action
|
||||
string $path,
|
||||
string $method,
|
||||
Document $user,
|
||||
string $jwt = null,
|
||||
string $event = null,
|
||||
?string $jwt = null,
|
||||
?string $event = null,
|
||||
): void {
|
||||
$executionId = ID::unique();
|
||||
$headers['x-appwrite-execution-id'] = $executionId ?? '';
|
||||
@@ -358,12 +358,12 @@ class Functions extends Action
|
||||
string $method,
|
||||
array $headers,
|
||||
array $platform,
|
||||
string $data = null,
|
||||
?string $data = null,
|
||||
?Document $user = null,
|
||||
string $jwt = null,
|
||||
string $event = null,
|
||||
string $eventData = null,
|
||||
string $executionId = null,
|
||||
?string $jwt = null,
|
||||
?string $event = null,
|
||||
?string $eventData = null,
|
||||
?string $executionId = null,
|
||||
): void {
|
||||
$user ??= new Document();
|
||||
$functionId = $function->getId();
|
||||
|
||||
@@ -131,7 +131,7 @@ class User extends Document
|
||||
return false;
|
||||
}
|
||||
|
||||
public function tokenVerify(int $type = null, string $secret, Proof $proofForToken): false|Document
|
||||
public function tokenVerify(?int $type, string $secret, Proof $proofForToken): false|Document
|
||||
{
|
||||
$tokens = $this->getAttribute('tokens', []);
|
||||
foreach ($tokens as $token) {
|
||||
|
||||
@@ -10,7 +10,7 @@ class BodyMultipart
|
||||
private array $parts = [];
|
||||
private string $boundary = "";
|
||||
|
||||
public function __construct(string $boundary = null)
|
||||
public function __construct(?string $boundary = null)
|
||||
{
|
||||
if (is_null($boundary)) {
|
||||
$this->boundary = self::generateBoundary();
|
||||
|
||||
@@ -1283,6 +1283,7 @@ class UsageTest extends Scope
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
$functionsDomain = \explode(',', System::getEnv('_APP_DOMAIN_FUNCTIONS', ''))[0];
|
||||
$rule = $this->client->call(
|
||||
Client::METHOD_POST,
|
||||
'/proxy/rules/function',
|
||||
@@ -1291,7 +1292,7 @@ class UsageTest extends Scope
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()),
|
||||
[
|
||||
'domain' => 'test-' . ID::unique() . '.' . System::getEnv('_APP_DOMAIN_FUNCTIONS'),
|
||||
'domain' => 'test-' . ID::unique() . '.' . $functionsDomain,
|
||||
'functionId' => $functionId,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -316,12 +316,13 @@ trait FunctionsBase
|
||||
|
||||
protected function setupFunctionDomain(string $functionId, string $subdomain = ''): string
|
||||
{
|
||||
$functionsDomain = \explode(',', System::getEnv('_APP_DOMAIN_FUNCTIONS', ''))[0];
|
||||
$subdomain = $subdomain ? $subdomain : ID::unique();
|
||||
$rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/function', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_FUNCTIONS', ''),
|
||||
'domain' => $subdomain . '.' . $functionsDomain,
|
||||
'functionId' => $functionId,
|
||||
]);
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class ProjectsCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
$functionsDomain = \explode(',', System::getEnv('_APP_DOMAIN_FUNCTIONS', ''))[0];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $headers, [
|
||||
'domain' => $functionsDomain,
|
||||
@@ -59,7 +59,7 @@ class ProjectsCustomServerTest extends Scope
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$sitesDomain = \explode(',', System::getEnv('_APP_DOMAIN_SITES', ''))[0];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $headers, [
|
||||
'domain' => $sitesDomain,
|
||||
|
||||
@@ -112,7 +112,8 @@ class ProxyCustomServerTest extends Scope
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
|
||||
$domain = \uniqid() . '-vcs.' . System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$sitesDomain = \explode(',', System::getEnv('_APP_DOMAIN_SITES', ''))[0];
|
||||
$domain = \uniqid() . '-vcs.' . $sitesDomain;
|
||||
|
||||
$rule = $this->createSiteRule('commit-' . $domain, $siteId);
|
||||
$this->assertEquals(400, $rule['headers']['status-code']);
|
||||
@@ -292,11 +293,28 @@ class ProxyCustomServerTest extends Scope
|
||||
|
||||
$ruleId = $this->setupSiteRule($domain, $siteId);
|
||||
$this->assertNotEmpty($ruleId);
|
||||
$rule = $this->getRule($ruleId);
|
||||
$this->assertSame(200, $rule['headers']['status-code']);
|
||||
$this->assertSame('created', $rule['body']['status']);
|
||||
|
||||
$response = $proxyClient->call(Client::METHOD_GET, '/contact');
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertStringContainsString('Contact page', $response['body']);
|
||||
|
||||
// Wildcard domains automatically get verified status
|
||||
$domains = [
|
||||
\uniqid() . '.sites.localhost',
|
||||
\uniqid() . '.rebranded.localhost',
|
||||
];
|
||||
foreach ($domains as $domain) {
|
||||
$wildcardRuleId = $this->setupSiteRule($domain, $siteId);
|
||||
$this->assertNotEmpty($wildcardRuleId);
|
||||
$rule = $this->getRule($wildcardRuleId);
|
||||
$this->assertSame(200, $rule['headers']['status-code']);
|
||||
$this->assertSame('verified', $rule['body']['status']);
|
||||
$this->cleanupRule($wildcardRuleId);
|
||||
}
|
||||
|
||||
$rules = $this->listRules([
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
@@ -384,7 +402,8 @@ class ProxyCustomServerTest extends Scope
|
||||
public function testUpdateRule(): void
|
||||
{
|
||||
// Create function appwrite-network domain
|
||||
$domain = \uniqid() . '-cname-api.' . System::getEnv('_APP_DOMAIN_FUNCTIONS');
|
||||
$functionsDomain = \explode(',', System::getEnv('_APP_DOMAIN_FUNCTIONS', ''))[0];
|
||||
$domain = \uniqid() . '-cname-api.' . $functionsDomain;
|
||||
|
||||
$rule = $this->createAPIRule($domain);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
@@ -393,7 +412,8 @@ class ProxyCustomServerTest extends Scope
|
||||
$this->cleanupRule($rule['body']['$id']);
|
||||
|
||||
// Create site appwrite-network domain
|
||||
$domain = \uniqid() . '-cname-api.' . System::getEnv('_APP_DOMAIN_SITES');
|
||||
$sitesDomain = \explode(',', System::getEnv('_APP_DOMAIN_SITES', ''))[0];
|
||||
$domain = \uniqid() . '-cname-api.' . $sitesDomain;
|
||||
|
||||
$rule = $this->createAPIRule($domain);
|
||||
$this->assertEquals(201, $rule['headers']['status-code']);
|
||||
|
||||
@@ -368,12 +368,13 @@ trait SitesBase
|
||||
|
||||
protected function setupSiteDomain(string $siteId, string $subdomain = ''): string
|
||||
{
|
||||
$sitesDomain = \explode(',', System::getEnv('_APP_DOMAIN_SITES', ''))[0];
|
||||
$subdomain = $subdomain ? $subdomain : ID::unique();
|
||||
$rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/site', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
'domain' => $subdomain . '.' . $sitesDomain,
|
||||
'siteId' => $siteId,
|
||||
]);
|
||||
|
||||
|
||||
@@ -1810,11 +1810,12 @@ class SitesCustomServerTest extends Scope
|
||||
|
||||
$siteId2 = $site2['body']['$id'];
|
||||
|
||||
$sitesDomain = \explode(',', System::getEnv('_APP_DOMAIN_SITES', ''))[0];
|
||||
$rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/site', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_SITES', ''),
|
||||
'domain' => $subdomain . '.' . $sitesDomain,
|
||||
'siteId' => $siteId2,
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user