mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch 'feat-sites' into feat-preview-branding
This commit is contained in:
@@ -1185,6 +1185,39 @@ return [
|
||||
'default' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('personalAccessToken'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 256,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['encrypt'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('personalAccessTokenExpiry'),
|
||||
'type' => Database::VAR_DATETIME,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => false,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['datetime'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('personalRefreshToken'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 256,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['encrypt'],
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
|
||||
|
||||
@@ -868,6 +868,11 @@ return [
|
||||
'description' => 'Variable with the same ID already exists in this project. Try again with a different ID.',
|
||||
'code' => 409,
|
||||
],
|
||||
Exception::VARIABLE_CANNOT_UNSET_SECRET => [
|
||||
'name' => Exception::VARIABLE_CANNOT_UNSET_SECRET,
|
||||
'description' => 'Secret variables cannot be marked as non-secret. Please re-create the variable if this is your intention.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::GRAPHQL_NO_QUERY => [
|
||||
'name' => Exception::GRAPHQL_NO_QUERY,
|
||||
'description' => 'Param "query" is not optional.',
|
||||
|
||||
@@ -127,6 +127,56 @@ return [
|
||||
'providerVersion' => '0.2.*',
|
||||
'variables' => [],
|
||||
],
|
||||
[
|
||||
'key' => 'sveltekit-with-appwrite',
|
||||
'name' => 'SvelteKit with Appwrite',
|
||||
'useCases' => ['starter'],
|
||||
'demoUrl' => '',
|
||||
'demoImage' => '',
|
||||
'frameworks' => [
|
||||
getFramework('SVELTEKIT', [
|
||||
'providerRootDirectory' => './',
|
||||
]),
|
||||
],
|
||||
'vcsProvider' => 'github',
|
||||
'providerRepositoryId' => 'starter-for-svelte',
|
||||
'providerOwner' => 'appwrite',
|
||||
'providerVersion' => '0.1.*',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => 'PUBLIC_APPWRITE_ENDPOINT',
|
||||
'description' => 'Endpoint of Appwrite server.',
|
||||
'value' => 'https://cloud.appwrite.io/v1',
|
||||
'placeholder' => 'https://cloud.appwrite.io/v1',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'PUBLIC_APPWRITE_PROJECT_ID',
|
||||
'description' => 'Your Appwrite project ID.',
|
||||
'value' => '',
|
||||
'placeholder' => '67ab5b6d000db4f5f59d',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'PUBLIC_APPWRITE_PROJECT_NAME',
|
||||
'description' => 'Your Appwrite project name.',
|
||||
'value' => '',
|
||||
'placeholder' => 'My project',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'PUBLIC_APPWRITE_VERSION',
|
||||
'description' => 'Version of Appwrite server.',
|
||||
'value' => '1.7.0',
|
||||
'placeholder' => '1.7.0',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'key' => 'astro-starter',
|
||||
'name' => 'Astro starter website',
|
||||
|
||||
@@ -7,4 +7,5 @@ return [
|
||||
"gif" => "image/gif",
|
||||
"png" => "image/png",
|
||||
"heic" => "image/heic",
|
||||
"webp" => "image/webp",
|
||||
];
|
||||
|
||||
@@ -1585,7 +1585,7 @@ App::post('/v1/functions/:functionId/variables')
|
||||
->param('functionId', '', new UID(), 'Function unique ID.', false)
|
||||
->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false)
|
||||
->param('secret', false, new Boolean(), 'Is secret? Secret variables can only be updated or deleted, they cannot be read.', true)
|
||||
->param('secret', true, new Boolean(), 'Secret variables can be updated or deleted, but only functions can read them during build and runtime.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
@@ -1729,10 +1729,11 @@ App::put('/v1/functions/:functionId/variables/:variableId')
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true)
|
||||
->param('secret', null, new Boolean(), 'Secret variables can be updated or deleted, but only functions can read them during build and runtime.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForPlatform) {
|
||||
->action(function (string $functionId, string $variableId, string $key, ?string $value, ?bool $secret, Response $response, Database $dbForProject, Database $dbForPlatform) {
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
@@ -1749,9 +1750,14 @@ App::put('/v1/functions/:functionId/variables/:variableId')
|
||||
throw new Exception(Exception::VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($variable->getAttribute('secret') === true && $secret === false) {
|
||||
throw new Exception(Exception::VARIABLE_CANNOT_UNSET_SECRET);
|
||||
}
|
||||
|
||||
$variable
|
||||
->setAttribute('key', $key)
|
||||
->setAttribute('value', $value ?? $variable->getAttribute('value'))
|
||||
->setAttribute('secret', $secret ?? $variable->getAttribute('secret'))
|
||||
->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key, 'function']));
|
||||
|
||||
try {
|
||||
|
||||
@@ -388,7 +388,7 @@ App::post('/v1/project/variables')
|
||||
))
|
||||
->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false)
|
||||
->param('secret', false, new Boolean(), 'Is secret? Secret variables can only be updated or deleted, they cannot be read.', true)
|
||||
->param('secret', true, new Boolean(), 'Secret variables can be updated or deleted, but only projects can read them during build and runtime.', true)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -509,19 +509,25 @@ App::put('/v1/project/variables/:variableId')
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true)
|
||||
->param('secret', null, new Boolean(), 'Secret variables can be updated or deleted, but only projects can read them during build and runtime.', true)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $variableId, string $key, ?string $value, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) {
|
||||
->action(function (string $variableId, string $key, ?string $value, ?bool $secret, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) {
|
||||
$variable = $dbForProject->getDocument('variables', $variableId);
|
||||
if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceType') !== 'project') {
|
||||
throw new Exception(Exception::VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($variable->getAttribute('secret') === true && $secret === false) {
|
||||
throw new Exception(Exception::VARIABLE_CANNOT_UNSET_SECRET);
|
||||
}
|
||||
|
||||
$variable
|
||||
->setAttribute('key', $key)
|
||||
->setAttribute('value', $value ?? $variable->getAttribute('value'))
|
||||
->setAttribute('secret', $secret ?? $variable->getAttribute('secret'))
|
||||
->setAttribute('search', implode(' ', [$variableId, $key, 'project']));
|
||||
|
||||
try {
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ services:
|
||||
appwrite-console:
|
||||
<<: *x-logging
|
||||
container_name: appwrite-console
|
||||
image: appwrite/console:5.3.0-sites-rc.4
|
||||
image: appwrite/console:5.3.0-sites-rc.5
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
|
||||
@@ -255,6 +255,7 @@ class Exception extends \Exception
|
||||
/** Variables */
|
||||
public const VARIABLE_NOT_FOUND = 'variable_not_found';
|
||||
public const VARIABLE_ALREADY_EXISTS = 'variable_already_exists';
|
||||
public const VARIABLE_CANNOT_UNSET_SECRET = 'variable_cannot_unset_secret';
|
||||
|
||||
/** Platform */
|
||||
public const PLATFORM_NOT_FOUND = 'platform_not_found';
|
||||
|
||||
@@ -56,14 +56,13 @@ class Create extends Base
|
||||
->param('siteId', '', new UID(), 'Site unique ID.', false)
|
||||
->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false)
|
||||
->param('secret', false, new Boolean(), 'Is secret? Secret variables can only be updated or deleted, they cannot be read.', true)
|
||||
->param('secret', true, new Boolean(), 'Secret variables can be updated or deleted, but only sites can read them during build and runtime.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $key, string $value, bool $secret, Response $response, Database $dbForProject, Database $dbForPlatform)
|
||||
public function action(string $siteId, string $key, string $value, bool $secret, Response $response, Database $dbForProject)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ 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\Text;
|
||||
|
||||
class Update extends Base
|
||||
@@ -52,12 +53,13 @@ class Update extends Base
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true)
|
||||
->param('secret', null, new Boolean(), 'Secret variables can be updated or deleted, but only sites can read them during build and runtime.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject)
|
||||
public function action(string $siteId, string $variableId, string $key, ?string $value, ?bool $secret, Response $response, Database $dbForProject)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
|
||||
@@ -74,9 +76,14 @@ class Update extends Base
|
||||
throw new Exception(Exception::VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($variable->getAttribute('secret') === true && $secret === false) {
|
||||
throw new Exception(Exception::VARIABLE_CANNOT_UNSET_SECRET);
|
||||
}
|
||||
|
||||
$variable
|
||||
->setAttribute('key', $key)
|
||||
->setAttribute('value', $value ?? $variable->getAttribute('value'))
|
||||
->setAttribute('secret', $secret ?? $variable->getAttribute('secret'))
|
||||
->setAttribute('search', implode(' ', [$variableId, $site->getId(), $key, 'site']));
|
||||
|
||||
try {
|
||||
|
||||
@@ -82,6 +82,46 @@ trait FunctionsBase
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function getVariable(string $functionId, string $variableId): mixed
|
||||
{
|
||||
$variable = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/variables/' . $variableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function updateVariable(string $functionId, string $variableId, mixed $params): mixed
|
||||
{
|
||||
$variable = $this->client->call(Client::METHOD_PUT, '/functions/' . $functionId . '/variables/' . $variableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function listVariables(string $functionId, mixed $params = []): mixed
|
||||
{
|
||||
$variables = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/variables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $variables;
|
||||
}
|
||||
|
||||
protected function deleteVariable(string $functionId, string $variableId): mixed
|
||||
{
|
||||
$variable = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId . '/variables/' . $variableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function getFunction(string $functionId): mixed
|
||||
{
|
||||
$function = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId, array_merge([
|
||||
|
||||
@@ -110,7 +110,8 @@ class FunctionsConsoleClientTest extends Scope
|
||||
$data['functionId'],
|
||||
[
|
||||
'key' => 'APP_TEST',
|
||||
'value' => 'TESTINGVALUE'
|
||||
'value' => 'TESTINGVALUE',
|
||||
'secret' => false
|
||||
]
|
||||
);
|
||||
|
||||
@@ -131,6 +132,7 @@ class FunctionsConsoleClientTest extends Scope
|
||||
$this->assertEquals(201, $variable['headers']['status-code']);
|
||||
$this->assertEquals('APP_TEST_1', $variable['body']['key']);
|
||||
$this->assertEmpty($variable['body']['value']);
|
||||
$this->assertTrue($variable['body']['secret']);
|
||||
|
||||
$secretVariableId = $variable['body']['$id'];
|
||||
|
||||
@@ -142,7 +144,8 @@ class FunctionsConsoleClientTest extends Scope
|
||||
$data['functionId'],
|
||||
[
|
||||
'key' => 'APP_TEST',
|
||||
'value' => 'ANOTHERTESTINGVALUE'
|
||||
'value' => 'ANOTHERTESTINGVALUE',
|
||||
'secret' => false
|
||||
]
|
||||
);
|
||||
|
||||
@@ -320,6 +323,41 @@ class FunctionsConsoleClientTest extends Scope
|
||||
$this->assertEquals("APP_TEST_UPDATE_2", $variable['body']['key']);
|
||||
$this->assertEquals("TESTINGVALUEUPDATED", $variable['body']['value']);
|
||||
|
||||
// convert non-secret variable to secret
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'key' => 'APP_TEST_UPDATE_2',
|
||||
'secret' => true
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals("APP_TEST_UPDATE_2", $response['body']['key']);
|
||||
$this->assertEmpty($response['body']['value']);
|
||||
$this->assertTrue($response['body']['secret']);
|
||||
|
||||
$variable = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $variable['headers']['status-code']);
|
||||
$this->assertEquals("APP_TEST_UPDATE_2", $variable['body']['key']);
|
||||
$this->assertEmpty($variable['body']['value']);
|
||||
$this->assertTrue($variable['body']['secret']);
|
||||
|
||||
// convert secret variable to non-secret
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'key' => 'APP_TEST_UPDATE',
|
||||
'secret' => false
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
*/
|
||||
@@ -410,4 +448,53 @@ class FunctionsConsoleClientTest extends Scope
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function testVariableE2E(): void
|
||||
{
|
||||
$function = $this->createFunction([
|
||||
'functionId' => ID::unique(),
|
||||
'runtime' => 'node-18.0',
|
||||
'name' => 'Variable E2E Test',
|
||||
'entrypoint' => 'index.js',
|
||||
'logging' => false,
|
||||
'execute' => ['any']
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $function['headers']['status-code']);
|
||||
$this->assertFalse($function['body']['logging']);
|
||||
$this->assertNotEmpty($function['body']['$id']);
|
||||
|
||||
$functionId = $function['body']['$id'] ?? '';
|
||||
|
||||
// create variable
|
||||
$variable = $this->createVariable($functionId, [
|
||||
'key' => 'CUSTOM_VARIABLE',
|
||||
'value' => 'a_secret_value',
|
||||
'secret' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $variable['headers']['status-code']);
|
||||
$this->assertNotEmpty($variable['body']['$id']);
|
||||
$this->assertEquals('CUSTOM_VARIABLE', $variable['body']['key']);
|
||||
$this->assertEquals('', $variable['body']['value']);
|
||||
$this->assertEquals(true, $variable['body']['secret']);
|
||||
|
||||
$deploymentId = $this->setupDeployment($functionId, [
|
||||
'entrypoint' => 'index.js',
|
||||
'code' => $this->packageFunction('node'),
|
||||
'activate' => true
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($deploymentId);
|
||||
|
||||
$execution = $this->createExecution($functionId);
|
||||
|
||||
$this->assertEquals(201, $execution['headers']['status-code']);
|
||||
$this->assertEmpty($execution['body']['logs']);
|
||||
$this->assertEmpty($execution['body']['errors']);
|
||||
$body = json_decode($execution['body']['responseBody']);
|
||||
$this->assertEquals('a_secret_value', $body->CUSTOM_VARIABLE);
|
||||
|
||||
$this->cleanupFunction($functionId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class FunctionsCustomServerTest extends Scope
|
||||
'timeout' => 10,
|
||||
]);
|
||||
|
||||
$functionId = $functionId = $function['body']['$id'] ?? '';
|
||||
$functionId = $function['body']['$id'] ?? '';
|
||||
|
||||
$dateValidator = new DatetimeValidator();
|
||||
$this->assertEquals(201, $function['headers']['status-code']);
|
||||
@@ -356,7 +356,7 @@ class FunctionsCustomServerTest extends Scope
|
||||
$this->assertEquals(201, $function['headers']['status-code']);
|
||||
$this->assertNotEmpty($function['body']['$id']);
|
||||
|
||||
$functionId = $functionId = $function['body']['$id'] ?? '';
|
||||
$functionId = $function['body']['$id'] ?? '';
|
||||
|
||||
$deployments = $this->listDeployments($functionId);
|
||||
|
||||
@@ -1898,7 +1898,7 @@ class FunctionsCustomServerTest extends Scope
|
||||
$this->assertFalse($function['body']['logging']);
|
||||
$this->assertNotEmpty($function['body']['$id']);
|
||||
|
||||
$functionId = $functionId = $function['body']['$id'] ?? '';
|
||||
$functionId = $function['body']['$id'] ?? '';
|
||||
|
||||
$this->setupDeployment($functionId, [
|
||||
'code' => $this->packageFunction('node'),
|
||||
|
||||
@@ -3923,10 +3923,14 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'x-appwrite-mode' => 'admin',
|
||||
], $this->getHeaders()), [
|
||||
'key' => 'APP_TEST',
|
||||
'value' => 'TESTINGVALUE'
|
||||
'value' => 'TESTINGVALUE',
|
||||
'secret' => false
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $variable['headers']['status-code']);
|
||||
$this->assertEquals('APP_TEST', $variable['body']['key']);
|
||||
$this->assertEquals('TESTINGVALUE', $variable['body']['value']);
|
||||
$this->assertFalse($variable['body']['secret']);
|
||||
$variableId = $variable['body']['$id'];
|
||||
|
||||
// test for secret variable
|
||||
@@ -4047,6 +4051,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals("APP_TEST_1", $response['body']['key']);
|
||||
$this->assertEmpty($response['body']['value']);
|
||||
$this->assertTrue($response['body']['secret']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
@@ -4118,6 +4123,17 @@ class ProjectsConsoleClientTest extends Scope
|
||||
$this->assertEquals("APP_TEST_UPDATE_1", $variable['body']['key']);
|
||||
$this->assertEmpty($variable['body']['value']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/project/variables/' . $data['secretVariableId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $data['projectId'],
|
||||
'x-appwrite-mode' => 'admin',
|
||||
], $this->getHeaders()), [
|
||||
'key' => 'APP_TEST_UPDATE_1',
|
||||
'secret' => false,
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/project/variables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $data['projectId'],
|
||||
|
||||
@@ -104,6 +104,46 @@ trait SitesBase
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function getVariable(string $siteId, string $variableId): mixed
|
||||
{
|
||||
$variable = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/variables/' . $variableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function listVariables(string $siteId, mixed $params = []): mixed
|
||||
{
|
||||
$variables = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/variables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $variables;
|
||||
}
|
||||
|
||||
protected function updateVariable(string $siteId, string $variableId, mixed $params): mixed
|
||||
{
|
||||
$variable = $this->client->call(Client::METHOD_PUT, '/sites/' . $siteId . '/variables/' . $variableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function deleteVariable(string $siteId, string $variableId): mixed
|
||||
{
|
||||
$variable = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId . '/variables/' . $variableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function getSite(string $siteId): mixed
|
||||
{
|
||||
$site = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId, array_merge([
|
||||
|
||||
@@ -65,6 +65,193 @@ class SitesCustomServerTest extends Scope
|
||||
$this->cleanupSite($siteId);
|
||||
}
|
||||
|
||||
public function testVariables(): void
|
||||
{
|
||||
$site = $this->createSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'framework' => 'other',
|
||||
'name' => 'Test Site',
|
||||
'outputDirectory' => './',
|
||||
'siteId' => ID::unique()
|
||||
]);
|
||||
|
||||
$siteId = $site['body']['$id'] ?? '';
|
||||
|
||||
$this->assertEquals(201, $site['headers']['status-code']);
|
||||
$this->assertNotEmpty($site['body']['$id']);
|
||||
$this->assertEquals('Test Site', $site['body']['name']);
|
||||
|
||||
$variable = $this->createVariable($siteId, [
|
||||
'key' => 'siteKey1',
|
||||
'value' => 'siteValue1',
|
||||
'secret' => false,
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $variable['headers']['status-code']);
|
||||
$this->assertNotEmpty($variable['body']['$id']);
|
||||
$this->assertEquals('siteKey1', $variable['body']['key']);
|
||||
$this->assertEquals('siteValue1', $variable['body']['value']);
|
||||
$this->assertEquals(false, $variable['body']['secret']);
|
||||
|
||||
$variable2 = $this->createVariable($siteId, [
|
||||
'key' => 'siteKey2',
|
||||
'value' => 'siteValue2',
|
||||
'secret' => false,
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $variable2['headers']['status-code']);
|
||||
$this->assertNotEmpty($variable2['body']['$id']);
|
||||
$this->assertEquals('siteKey2', $variable2['body']['key']);
|
||||
$this->assertEquals('siteValue2', $variable2['body']['value']);
|
||||
$this->assertEquals(false, $variable2['body']['secret']);
|
||||
|
||||
$secretVariable = $this->createVariable($siteId, [
|
||||
'key' => 'siteKey3',
|
||||
'value' => 'siteValue3',
|
||||
'secret' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $secretVariable['headers']['status-code']);
|
||||
$this->assertNotEmpty($secretVariable['body']['$id']);
|
||||
$this->assertEquals('siteKey3', $secretVariable['body']['key']);
|
||||
$this->assertEquals('', $secretVariable['body']['value']);
|
||||
$this->assertEquals(true, $secretVariable['body']['secret']);
|
||||
|
||||
$variable = $this->getVariable($siteId, $variable['body']['$id']);
|
||||
|
||||
$this->assertEquals(200, $variable['headers']['status-code']);
|
||||
$this->assertNotEmpty($variable['body']['$id']);
|
||||
$this->assertEquals('siteKey1', $variable['body']['key']);
|
||||
$this->assertEquals('siteValue1', $variable['body']['value']);
|
||||
$this->assertEquals(false, $variable['body']['secret']);
|
||||
|
||||
$secretVariable = $this->getVariable($siteId, $secretVariable['body']['$id']);
|
||||
|
||||
$this->assertEquals(200, $secretVariable['headers']['status-code']);
|
||||
$this->assertNotEmpty($secretVariable['body']['$id']);
|
||||
$this->assertEquals('siteKey3', $secretVariable['body']['key']);
|
||||
$this->assertEquals('', $secretVariable['body']['value']);
|
||||
$this->assertEquals(true, $secretVariable['body']['secret']);
|
||||
|
||||
$variable = $this->updateVariable($siteId, $variable['body']['$id'], [
|
||||
'key' => 'siteKey1Updated',
|
||||
'value' => 'siteValue1Updated',
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $variable['headers']['status-code']);
|
||||
$this->assertNotEmpty($variable['body']['$id']);
|
||||
$this->assertEquals('siteKey1Updated', $variable['body']['key']);
|
||||
$this->assertEquals('siteValue1Updated', $variable['body']['value']);
|
||||
$this->assertEquals(false, $variable['body']['secret']);
|
||||
|
||||
$variable = $this->updateVariable($siteId, $variable['body']['$id'], [
|
||||
'key' => 'siteKey1Updated',
|
||||
'secret' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $variable['headers']['status-code']);
|
||||
$this->assertNotEmpty($variable['body']['$id']);
|
||||
$this->assertEquals('siteKey1Updated', $variable['body']['key']);
|
||||
$this->assertEquals('', $variable['body']['value']);
|
||||
$this->assertEquals(true, $variable['body']['secret']);
|
||||
|
||||
$secretVariable = $this->updateVariable($siteId, $secretVariable['body']['$id'], [
|
||||
'key' => 'siteKey3',
|
||||
'value' => 'siteValue3Updated',
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $secretVariable['headers']['status-code']);
|
||||
$this->assertNotEmpty($secretVariable['body']['$id']);
|
||||
$this->assertEquals('siteKey3', $secretVariable['body']['key']);
|
||||
$this->assertEquals('', $secretVariable['body']['value']);
|
||||
$this->assertEquals(true, $secretVariable['body']['secret']);
|
||||
|
||||
$response = $this->updateVariable($siteId, $secretVariable['body']['$id'], [
|
||||
'key' => 'siteKey3',
|
||||
'secret' => false,
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
$secretVariable = $this->getVariable($siteId, $secretVariable['body']['$id']);
|
||||
|
||||
$this->assertEquals(200, $secretVariable['headers']['status-code']);
|
||||
$this->assertNotEmpty($secretVariable['body']['$id']);
|
||||
$this->assertEquals('siteKey3', $secretVariable['body']['key']);
|
||||
$this->assertEquals('', $secretVariable['body']['value']);
|
||||
$this->assertEquals(true, $secretVariable['body']['secret']);
|
||||
|
||||
$variables = $this->listVariables($siteId);
|
||||
|
||||
$this->assertEquals(200, $variables['headers']['status-code']);
|
||||
$this->assertCount(3, $variables['body']['variables']);
|
||||
|
||||
$response = $this->deleteVariable($siteId, $variable['body']['$id']);
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
$response = $this->deleteVariable($siteId, $variable2['body']['$id']);
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
$response = $this->deleteVariable($siteId, $secretVariable['body']['$id']);
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
$variables = $this->listVariables($siteId);
|
||||
|
||||
$this->assertEquals(200, $variables['headers']['status-code']);
|
||||
$this->assertCount(0, $variables['body']['variables']);
|
||||
|
||||
$this->cleanupSite($siteId);
|
||||
}
|
||||
|
||||
public function testVariablesE2E(): void
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
'siteId' => ID::unique(),
|
||||
'name' => 'Astro site',
|
||||
'framework' => 'astro',
|
||||
'adapter' => 'ssr',
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'outputDirectory' => './dist',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'fallbackFile' => '',
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($siteId);
|
||||
|
||||
$secretVariable = $this->createVariable($siteId, [
|
||||
'key' => 'name',
|
||||
'value' => 'Appwrite',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $secretVariable['headers']['status-code']);
|
||||
$this->assertNotEmpty($secretVariable['body']['$id']);
|
||||
$this->assertEquals('name', $secretVariable['body']['key']);
|
||||
$this->assertEquals('', $secretVariable['body']['value']);
|
||||
$this->assertEquals(true, $secretVariable['body']['secret']);
|
||||
|
||||
$deploymentId = $this->setupDeployment($siteId, [
|
||||
'code' => $this->packageSite('astro'),
|
||||
'activate' => 'true'
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($deploymentId);
|
||||
|
||||
$domain = $this->getSiteDomain($siteId);
|
||||
$proxyClient = new Client();
|
||||
$proxyClient->setEndpoint('http://' . $domain);
|
||||
|
||||
$response = $proxyClient->call(Client::METHOD_GET, '/', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
]));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertStringContainsString("Env variable is Appwrite", $response['body']);
|
||||
$this->assertStringNotContainsString("Variable not found", $response['body']);
|
||||
|
||||
$this->cleanupSite($siteId);
|
||||
}
|
||||
|
||||
public function testListSites(): void
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import node from '@astrojs/node';
|
||||
import 'dotenv/config';
|
||||
|
||||
export default defineConfig({
|
||||
output: 'server',
|
||||
adapter: node({
|
||||
mode: 'standalone'
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "my-astro-app",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^9.0.2",
|
||||
"astro": "^5.2.5",
|
||||
"dotenv": "^16.4.7"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
const value = import.meta.env.name || 'Variable not found';
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Astro SSR</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Env variable is {value}</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [".astro/types.d.ts", "**/*"],
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user