mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 08:58:35 +00:00
Merge pull request #8970 from appwrite/feat-console-availability-endpoint
Add new console endpoint to check resource availability
This commit is contained in:
commit
c4142565aa
10 changed files with 207 additions and 8 deletions
|
|
@ -375,6 +375,13 @@ return [
|
|||
'code' => 409,
|
||||
],
|
||||
|
||||
/** Console */
|
||||
Exception::RESOURCE_ALREADY_EXISTS => [
|
||||
'name' => Exception::RESOURCE_ALREADY_EXISTS,
|
||||
'description' => 'Resource with the requested ID already exists. Please choose a different ID and try again.',
|
||||
'code' => 409,
|
||||
],
|
||||
|
||||
/** Membership */
|
||||
Exception::MEMBERSHIP_NOT_FOUND => [
|
||||
'name' => Exception::MEMBERSHIP_NOT_FOUND,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ $member = [
|
|||
'subscribers.write',
|
||||
'subscribers.read',
|
||||
'assistant.read',
|
||||
'rules.read'
|
||||
];
|
||||
|
||||
$admins = [
|
||||
|
|
|
|||
14
composer.lock
generated
14
composer.lock
generated
|
|
@ -4607,16 +4607,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/storage",
|
||||
"version": "0.18.8",
|
||||
"version": "0.18.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/storage.git",
|
||||
"reference": "84737afa634e6a833fc4f8b0c967553234d3f215"
|
||||
"reference": "1cf455404e8700b3093fd73d74a38d41cdced90c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/storage/zipball/84737afa634e6a833fc4f8b0c967553234d3f215",
|
||||
"reference": "84737afa634e6a833fc4f8b0c967553234d3f215",
|
||||
"url": "https://api.github.com/repos/utopia-php/storage/zipball/1cf455404e8700b3093fd73d74a38d41cdced90c",
|
||||
"reference": "1cf455404e8700b3093fd73d74a38d41cdced90c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -4656,9 +4656,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/storage/issues",
|
||||
"source": "https://github.com/utopia-php/storage/tree/0.18.8"
|
||||
"source": "https://github.com/utopia-php/storage/tree/0.18.9"
|
||||
},
|
||||
"time": "2024-12-04T08:30:35+00:00"
|
||||
"time": "2025-02-11T13:10:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/swoole",
|
||||
|
|
@ -8780,5 +8780,5 @@
|
|||
"platform-overrides": {
|
||||
"php": "8.3"
|
||||
},
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,9 @@ class Exception extends \Exception
|
|||
public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch';
|
||||
public const TEAM_ALREADY_EXISTS = 'team_already_exists';
|
||||
|
||||
/** Console */
|
||||
public const RESOURCE_ALREADY_EXISTS = 'resource_already_exists';
|
||||
|
||||
/** Membership */
|
||||
public const MEMBERSHIP_NOT_FOUND = 'membership_not_found';
|
||||
public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed';
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Appwrite\Platform;
|
||||
|
||||
use Appwrite\Platform\Modules\Console;
|
||||
use Appwrite\Platform\Modules\Core;
|
||||
use Appwrite\Platform\Modules\Functions;
|
||||
use Appwrite\Platform\Modules\Sites;
|
||||
|
|
@ -14,5 +15,6 @@ class Appwrite extends Platform
|
|||
parent::__construct(new Core());
|
||||
$this->addModule(new Functions\Module());
|
||||
$this->addModule(new Sites\Module());
|
||||
$this->addModule(new Console\Module());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
85
src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php
Normal file
85
src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Console\Http\Resources;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Domain;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'getResources';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
||||
->setHttpPath('/v1/console/resources')
|
||||
->desc('Check resource ID availability')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'rules.read')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'console',
|
||||
name: 'getResource',
|
||||
description: <<<EOT
|
||||
Check if a resource ID is available.
|
||||
EOT,
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_NOCONTENT,
|
||||
model: Response::MODEL_NONE,
|
||||
)
|
||||
],
|
||||
contentType: ContentType::NONE,
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'userId:{userId}, url:{url}')
|
||||
->label('abuse-time', 60)
|
||||
->param('value', '', new Text(256), 'Resource value.')
|
||||
->param('type', '', new WhiteList(['rules']), 'Resource type.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $value, string $type, Response $response, Database $dbForPlatform)
|
||||
{
|
||||
if ($type === 'rules') {
|
||||
$validator = new Domain($value);
|
||||
|
||||
if (!$validator->isValid($value)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $validator->getDescription());
|
||||
}
|
||||
|
||||
$document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$value]),
|
||||
]));
|
||||
|
||||
if (!$document->isEmpty()) {
|
||||
throw new Exception(Exception::RESOURCE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$response->noContent();
|
||||
}
|
||||
|
||||
// Only occurs if type is added into whitelist, but not supported in action
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid type');
|
||||
}
|
||||
}
|
||||
14
src/Appwrite/Platform/Modules/Console/Module.php
Normal file
14
src/Appwrite/Platform/Modules/Console/Module.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Console;
|
||||
|
||||
use Appwrite\Platform\Modules\Console\Services\Http;
|
||||
use Utopia\Platform;
|
||||
|
||||
class Module extends Platform\Module
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->addService('http', new Http());
|
||||
}
|
||||
}
|
||||
16
src/Appwrite/Platform/Modules/Console/Services/Http.php
Normal file
16
src/Appwrite/Platform/Modules/Console/Services/Http.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Console\Services;
|
||||
|
||||
use Appwrite\Platform\Modules\Console\Http\Resources\Get as GetResourceAvailability;
|
||||
use Utopia\Platform\Service;
|
||||
|
||||
class Http extends Service
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->type = Service::TYPE_HTTP;
|
||||
// Resources
|
||||
$this->addAction(GetResourceAvailability::getName(), new GetResourceAvailability());
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ trait SitesBase
|
|||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]));
|
||||
$this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT));
|
||||
}, 50000, 500);
|
||||
}, 100000, 500);
|
||||
|
||||
return $deploymentId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,77 @@ class SitesCustomServerTest extends Scope
|
|||
$this->cleanupSite($siteId);
|
||||
}
|
||||
|
||||
public function testConsoleAvailabilityEndpoint(): void
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
'siteId' => ID::unique(),
|
||||
'name' => 'Test Site',
|
||||
'framework' => 'other',
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'outputDirectory' => './',
|
||||
'subdomain' => 'test-site',
|
||||
'fallbackFile' => null,
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($siteId);
|
||||
|
||||
$rule = $this->getSiteDomain($siteId);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/console/resources', [
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
|
||||
'x-appwrite-project' => 'console',
|
||||
], [
|
||||
'type' => 'rules',
|
||||
'value' => $rule,
|
||||
]);
|
||||
|
||||
$this->assertEquals(409, $response['headers']['status-code']); // domain unavailable
|
||||
|
||||
$nonExistingDomain = "non-existent-subdomain.sites.localhost";
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/console/resources', [
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
|
||||
'x-appwrite-project' => 'console',
|
||||
], [
|
||||
'type' => 'rules',
|
||||
'value' => $nonExistingDomain,
|
||||
]);
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']); // domain available
|
||||
|
||||
$this->cleanupSite($siteId);
|
||||
|
||||
$this->assertEventually(function () use ($siteId) {
|
||||
$rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::equal('resourceId', [$siteId])
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $rule['headers']['status-code']);
|
||||
$this->assertEquals(0, $rule['body']['total']);
|
||||
}, 5000, 500);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/console/resources', [
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
|
||||
'x-appwrite-project' => 'console',
|
||||
], [
|
||||
'type' => 'rules',
|
||||
'value' => $rule,
|
||||
]);
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']); // domain available as site is deleted
|
||||
}
|
||||
|
||||
public function testVariables(): void
|
||||
{
|
||||
$site = $this->createSite([
|
||||
|
|
|
|||
Loading…
Reference in a new issue