From 2e1f67245d7a7265efcbf3ba0cd6f7258fcba054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 16 May 2024 08:39:15 +0000 Subject: [PATCH] Fix bugs, add old api key test --- app/controllers/api/projects.php | 2 +- app/controllers/mock.php | 50 +++++++++++++++++++ app/controllers/shared/api.php | 10 +++- src/Appwrite/Utopia/Response/Model/Key.php | 7 --- .../Databases/DatabasesCustomServerTest.php | 2 - .../Functions/FunctionsCustomServerTest.php | 2 - .../Projects/ProjectsConsoleClientTest.php | 39 +++++++++++++++ 7 files changed, 98 insertions(+), 14 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index cb75b76da5..d81c37a61c 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1148,7 +1148,7 @@ App::post('/v1/projects/:projectId/keys') 'expire' => $expire, 'sdks' => [], 'accessedAt' => null, - 'secret' => \bin2hex(\random_bytes(128)), + 'secret' => API_KEY_STANDARD . '_' . \bin2hex(\random_bytes(128)), ]); $key = $dbForConsole->createDocument('keys', $key); diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 6679fa14f5..fdb1d80dcc 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -6,6 +6,7 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\App; +use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; @@ -154,6 +155,55 @@ App::patch('/v1/mock/functions-v2') $response->noContent(); }); +App::post('/v1/mock/api-key-unprefixed') + ->desc('Create API Key (without standard prefix)') + ->groups(['mock', 'api', 'projects']) + ->label('scope', 'projects.write') + ->label('docs', false) + ->param('projectId', '', new UID(), 'Project ID.') + ->inject('response') + ->inject('dbForConsole') + ->action(function (string $projectId, Response $response, Database $dbForConsole) { + $isDevelopment = System::getEnv('_APP_ENV', 'development') === 'development'; + + if (!$isDevelopment) { + throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); + } + + $project = $dbForConsole->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + $scopes = array_keys(Config::getParam('scopes')); + + $key = new Document([ + '$id' => ID::unique(), + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'projectInternalId' => $project->getInternalId(), + 'projectId' => $project->getId(), + 'name' => 'Outdated key', + 'scopes' => $scopes, + 'expire' => null, + 'sdks' => [], + 'accessedAt' => null, + 'secret' => \bin2hex(\random_bytes(128)), + ]); + + $key = $dbForConsole->createDocument('keys', $key); + + $dbForConsole->purgeCachedDocument('projects', $project->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($key, Response::MODEL_KEY); + }); + App::get('/v1/mock/github/callback') ->desc('Create installation document using GitHub installation id') ->groups(['mock', 'api', 'vcs']) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index d08f208d82..fc6792a913 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -206,7 +206,12 @@ App::init() throw new Exception(Exception::USER_API_KEY_AND_SESSION_SET); } - [ $keyType, $authKey ] = \explode('_', $apiKey, 2); + if(!\str_contains($apiKey, '_')) { + $keyType = API_KEY_STANDARD; + $authKey = $apiKey; + } else { + [ $keyType, $authKey ] = \explode('_', $apiKey, 2); + } if($keyType === API_KEY_DYNAMIC) { // Dynamic key @@ -239,10 +244,11 @@ App::init() Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. } } elseif($keyType === API_KEY_STANDARD) { + // No underline means no prefix. Backwards compatibility. // Regular key // Check if given key match project API keys - $key = $project->find('secret', $authKey, 'keys'); + $key = $project->find('secret', $apiKey, 'keys'); if ($key) { $user = new Document([ '$id' => '', diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index 2dca87fdfe..1179a73d62 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -4,7 +4,6 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -use Utopia\Database\Document; class Key extends Model { @@ -94,10 +93,4 @@ class Key extends Model { return Response::MODEL_KEY; } - - public function filter(Document $document): Document - { - $document->setAttribute('secret', API_KEY_STANDARD . '_' . $document->getAttribute('secret', '')); - return $document; - } } diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 70bbedcb38..63fc3ca75f 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -1296,8 +1296,6 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders())); - \var_dump($attributes['body']); - $this->assertEquals(0, $attributes['body']['total']); } diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 4f71161773..6a8dc322e3 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -1444,8 +1444,6 @@ class FunctionsCustomServerTest extends Scope 'async' => false ]); - \var_dump($execution); - $this->assertEquals(201, $execution['headers']['status-code']); $this->assertEquals('completed', $execution['body']['status']); $this->assertEquals(200, $execution['body']['responseStatusCode']); diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 6f60f01c73..b07ca1c8f4 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -2704,6 +2704,45 @@ class ProjectsConsoleClientTest extends Scope return $data; } + /** + * @depends testCreateProject + */ + public function testCreateProjectKeyOutdated($data): void + { + $id = $data['projectId'] ?? ''; + + $response = $this->client->call(Client::METHOD_POST, '/mock/api-key-unprefixed', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'projectId' => $id + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertContains('users.read', $response['body']['scopes']); + $this->assertNotEmpty($response['body']['secret']); + $this->assertStringStartsNotWith(API_KEY_STANDARD . '_', $response['body']['secret']); + + $keyId = $response['body']['$id']; + $secret = $response['body']['secret']; + + $response = $this->client->call(Client::METHOD_GET, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-key' => $secret + ], []); + + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEmpty($response['body']); + } + // Platforms /**