diff --git a/app/config/locale/translations/en.json b/app/config/locale/translations/en.json index b16b50196f..937ab298de 100644 --- a/app/config/locale/translations/en.json +++ b/app/config/locale/translations/en.json @@ -20,7 +20,7 @@ "emails.magicSession.signature": "{{project}} team", "emails.sessionAlert.subject": "Security alert: new session on your {{project}} account", "emails.sessionAlert.hello":"Hello {{user}}", - "emails.sessionAlert.body": "A new session has been created on your {{b}}{{project}}{{/b}} account, on {{b}}{{dateTime}}{{/b}}.\nHere are the details of the new session: ", + "emails.sessionAlert.body": "A new session has been created on your {{b}}{{project}}{{/b}} account, {{b}}on {{date}}, {{year}} at {{time}} UTC{{/b}}.\nHere are the details of the new session: ", "emails.sessionAlert.listDevice": "Device: {{b}}{{device}}{{/b}}", "emails.sessionAlert.listIpAddress": "IP Address: {{b}}{{ipAddress}}{{/b}}", "emails.sessionAlert.listCountry": "Country: {{b}}{{country}}{{/b}}", diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 15c0ff9e97..17f3af4364 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -124,7 +124,9 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - 'dateTime' => DateTime::format(new \DateTime(), 'h:ia MMMM dS'), + 'date' => (new \DateTime())->format('F j'), + 'year' => (new \DateTime())->format('YYYY'), + 'time' => (new \DateTime())->format('H:i:s'), 'user' => $user->getAttribute('name'), 'project' => $project->getAttribute('name'), 'device' => $session->getAttribute('clientName'), diff --git a/app/controllers/general.php b/app/controllers/general.php index ff670c68ca..b79e3554db 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -97,6 +97,9 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $type = $route->getAttribute('resourceType'); if ($type === 'function') { + $utopia->getRoute()?->label('sdk.namespace', 'functions'); + $utopia->getRoute()?->label('sdk.method', 'createExecution'); + if (System::getEnv('_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS if ($request->getProtocol() !== 'https') { if ($request->getMethod() !== Request::METHOD_GET) { diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index a4c76a9a35..c02e140270 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -32,8 +32,9 @@ App::get('/') ->action(function (Request $request, Response $response) { $url = parse_url($request->getURI()); $target = "/console{$url['path']}"; - if ($url['query'] ?? false) { - $target .= "?{$url['query']}"; + $params = $request->getParams(); + if (!empty($params)) { + $target .= "?" . \http_build_query($params); } if ($url['fragment'] ?? false) { $target .= "#{$url['fragment']}"; diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index d03fe7bbb2..eda5fa1af2 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -166,7 +166,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:5.0.4 + image: /console:5.0.10 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index 3d3ac5c167..502c9dcd5c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -196,7 +196,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:5.0.4 + image: appwrite/console:5.0.10 restart: unless-stopped networks: - appwrite diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php index 242af6926f..41a10cee89 100644 --- a/src/Appwrite/Utopia/Response/Model/Document.php +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -72,7 +72,8 @@ class Document extends Any public function filter(DatabaseDocument $document): DatabaseDocument { $document->removeAttribute('$internalId'); - $document->removeAttribute('$collection'); // $collection is the internal collection ID + $document->removeAttribute('$collection'); + $document->removeAttribute('$tenant'); foreach ($document->getAttributes() as $attribute) { if (\is_array($attribute)) { diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index b6dd3543c6..0881966365 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -216,4 +216,17 @@ class HTTPTest extends Scope $this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin']); } + + public function testConsoleRedirect() + { + /** + * Test for SUCCESS + */ + + $endpoint = '/invite?membershipId=123&userId=asdf'; + + $response = $this->client->call(Client::METHOD_GET, $endpoint); + + $this->assertEquals('/console' . $endpoint, $response['headers']['location']); + } } diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 6ebd95aa5d..04f2dbd8c8 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1593,6 +1593,7 @@ trait DatabasesBase $this->assertEquals($response['body']['$permissions'], $document['$permissions']); $this->assertEquals($response['body']['birthDay'], $document['birthDay']); $this->assertFalse(array_key_exists('$internalId', $response['body'])); + $this->assertFalse(array_key_exists('$tenant', $response['body'])); } } diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 912a7a3f2c..7836a363c9 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -568,6 +568,36 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString("Total users: " . $totalusers, $execution['body']['logs']); + // Execute function again but async + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'path' => '/ping', + 'async' => true + ]); + + $this->assertEquals(202, $execution['headers']['status-code']); + $this->assertNotEmpty($execution['body']['$id']); + $this->assertEquals('waiting', $execution['body']['status']); + $executionId = $execution['body']['$id']; + + // Wait for async execuntion to finish + sleep(5); + + // Ensure execution was successful + $execution = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $execution['headers']['status-code']); + $this->assertEquals("completed", $execution['body']['status']); + $this->assertEquals(200, $execution['body']['responseStatusCode']); + $this->assertEmpty($execution['body']['responseBody']); + $this->assertEmpty($execution['body']['errors']); + $this->assertStringContainsString("Total users: " . $totalusers, $execution['body']['logs']); + // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json',