From e9c1e8e0b1bc112e22f5483c6dde05e8bf43733e Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Fri, 20 Nov 2020 14:35:16 +0200 Subject: [PATCH] Added new tests --- app/controllers/api/account.php | 20 ++-- tests/e2e/Scopes/ProjectCustom.php | 42 ++++++- tests/e2e/Services/Webhooks/WebhooksBase.php | 104 ++++++++++++++++++ .../Webhooks/WebhooksCustomClientTest.php | 14 +++ .../Webhooks/WebhooksCustomServerTest.php | 14 +++ 5 files changed, 185 insertions(+), 9 deletions(-) create mode 100644 tests/e2e/Services/Webhooks/WebhooksBase.php create mode 100644 tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php create mode 100644 tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index c42ebaa3cf..b6c531150f 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1165,7 +1165,7 @@ App::post('/v1/account/recovery') ->label('abuse-key', 'url:{url},email:{param-email}') ->param('email', '', new Email(), 'User email.') ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) - ->action(function ($email, $url, $request, $response, $projectDB, $project, $locale, $mails, $audits, $webhooks, $mode) { + ->action(function ($email, $url, $request, $response, $projectDB, $project, $locale, $mails, $audits, $webhooks) { /** @var Utopia\Swoole\Request $request */ /** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Database\Database $projectDB */ @@ -1174,7 +1174,9 @@ App::post('/v1/account/recovery') /** @var Appwrite\Event\Event $mails */ /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Event\Event $webhooks */ - /** @var bool $mode */ + + $isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles); + $isAppUser = Auth::isAppUser(Authorization::$roles); $profile = $projectDB->getCollectionFirst([ // Get user by email address 'limit' => 1, @@ -1258,7 +1260,7 @@ App::post('/v1/account/recovery') $recovery // Hide secret for clients, sp ->setAttribute('secret', - ((APP_MODE_ADMIN === $mode)) ? $secret : ''); + ($isPreviliggedUser || $isAppUser) ? $secret : ''); $audits ->setParam('userId', $profile->getId()) @@ -1270,7 +1272,7 @@ App::post('/v1/account/recovery') ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($recovery, Response::MODEL_TOKEN) ; - }, ['request', 'response', 'projectDB', 'project', 'locale', 'mails', 'audits', 'webhooks', 'mode']); + }, ['request', 'response', 'projectDB', 'project', 'locale', 'mails', 'audits', 'webhooks']); App::put('/v1/account/recovery') ->desc('Complete Password Recovery') @@ -1362,7 +1364,7 @@ App::post('/v1/account/verification') ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},email:{param-email}') ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page - ->action(function ($url, $request, $response, $project, $user, $projectDB, $locale, $audits, $webhooks, $mails, $mode) { + ->action(function ($url, $request, $response, $project, $user, $projectDB, $locale, $audits, $webhooks, $mails) { /** @var Utopia\Swoole\Request $request */ /** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Database\Document $project */ @@ -1372,7 +1374,9 @@ App::post('/v1/account/verification') /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Event\Event $webhooks */ /** @var Appwrite\Event\Event $mails */ - /** @var bool $mode */ + + $isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles); + $isAppUser = Auth::isAppUser(Authorization::$roles); $verificationSecret = Auth::tokenGenerator(); @@ -1445,7 +1449,7 @@ App::post('/v1/account/verification') $verification // Hide secret for clients, sp ->setAttribute('secret', - ((APP_MODE_ADMIN === $mode)) ? $verificationSecret : ''); + ($isPreviliggedUser || $isAppUser) ? $verificationSecret : ''); $audits ->setParam('userId', $user->getId()) @@ -1457,7 +1461,7 @@ App::post('/v1/account/verification') ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($verification, Response::MODEL_TOKEN) ; - }, ['request', 'response', 'project', 'user', 'projectDB', 'locale', 'audits', 'webhooks', 'mails', 'mode']); + }, ['request', 'response', 'project', 'user', 'projectDB', 'locale', 'audits', 'webhooks', 'mails']); App::put('/v1/account/verification') ->desc('Complete Email Verification') diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index 831a0fbb7a..e900e4e74f 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -81,10 +81,50 @@ trait ProjectCustom ], ]); - $this->assertEquals(201, $project['headers']['status-code']); + $this->assertEquals(201, $key['headers']['status-code']); $this->assertNotEmpty($key['body']); $this->assertNotEmpty($key['body']['secret']); + $webhook = $this->client->call(Client::METHOD_POST, '/projects/'.$project['body']['$id'].'/webhooks', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Webhook Test', + 'events' => [ + 'account.create', + 'account.update.email', + 'account.update.name', + 'account.update.password', + 'account.update.prefs', + 'account.recovery.create', + 'account.recovery.update', + 'account.delete', + 'account.sessions.create', + 'account.sessions.delete', + 'database.collections.create', + 'database.collections.update', + 'database.collections.delete', + 'database.documents.create', + 'database.documents.patch', + 'database.documents.delete', + 'storage.files.create', + 'storage.files.update', + 'storage.files.delete', + 'users.create', + 'users.update.status', + 'users.delete', + 'users.sessions.delete', + ], + 'url' => 'http://request-catcher:5000/webhook', + 'security' => false, + 'httpUser' => '', + 'httpPass' => '', + ]); + + $this->assertEquals(201, $webhook['headers']['status-code']); + $this->assertNotEmpty($webhook['body']); + $this->assertNotEmpty($webhook['body']['secret']); + // return [ // 'email' => $this->demoEmail, // 'password' => $this->demoPassword, diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php new file mode 100644 index 0000000000..9221fcbcf1 --- /dev/null +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -0,0 +1,104 @@ +client->call(Client::METHOD_POST, '/storage/files', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'read' => ['*'], + 'write' => ['*'], + 'folderId' => 'xyz', + ]); + + $this->assertEquals($file['headers']['status-code'], 201); + $this->assertNotEmpty($file['body']['$id']); + + $webhook = $this->getLastRequest(); + + var_dump($webhook); + + /** + * Test for FAILURE + */ + return ['fileId' => $file['body']['$id']]; + } + + // /** + // * @depends testCreateFile + // */ + // public function testGetFile(array $data):array + // { + // /** + // * Test for SUCCESS + // */ + // $file1 = $this->client->call(Client::METHOD_GET, '/storage/files/' . $data['fileId'], array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $this->getProject()['$id'], + // ], $this->getHeaders())); + + // $this->assertEquals($file1['headers']['status-code'], 200); + // $this->assertNotEmpty($file1['body']['$id']); + // $this->assertIsInt($file1['body']['dateCreated']); + // $this->assertEquals('logo.png', $file1['body']['name']); + // $this->assertEquals('image/png', $file1['body']['mimeType']); + // $this->assertEquals(47218, $file1['body']['sizeOriginal']); + // //$this->assertEquals(54944, $file1['body']['sizeActual']); + // //$this->assertEquals('gzip', $file1['body']['algorithm']); + // //$this->assertEquals('1', $file1['body']['fileOpenSSLVersion']); + // //$this->assertEquals('aes-128-gcm', $file1['body']['fileOpenSSLCipher']); + // //$this->assertNotEmpty($file1['body']['fileOpenSSLTag']); + // //$this->assertNotEmpty($file1['body']['fileOpenSSLIV']); + // $this->assertIsArray($file1['body']['$permissions']['read']); + // $this->assertIsArray($file1['body']['$permissions']['write']); + // $this->assertCount(1, $file1['body']['$permissions']['read']); + // $this->assertCount(1, $file1['body']['$permissions']['write']); + + // $file2 = $this->client->call(Client::METHOD_GET, '/storage/files/' . $data['fileId'] . '/preview', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $this->getProject()['$id'], + // ], $this->getHeaders())); + + // $this->assertEquals(200, $file2['headers']['status-code']); + // $this->assertEquals('image/png', $file2['headers']['content-type']); + // $this->assertNotEmpty($file2['body']); + + // $file3 = $this->client->call(Client::METHOD_GET, '/storage/files/' . $data['fileId'] . '/download', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $this->getProject()['$id'], + // ], $this->getHeaders())); + + // $this->assertEquals(200, $file3['headers']['status-code']); + // $this->assertEquals('attachment; filename="logo.png"', $file3['headers']['content-disposition']); + // $this->assertEquals('image/png', $file3['headers']['content-type']); + // $this->assertNotEmpty($file3['body']); + + // $file4 = $this->client->call(Client::METHOD_GET, '/storage/files/' . $data['fileId'] . '/view', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $this->getProject()['$id'], + // ], $this->getHeaders())); + + // $this->assertEquals(200, $file4['headers']['status-code']); + // $this->assertEquals('image/png', $file4['headers']['content-type']); + // $this->assertNotEmpty($file4['body']); + + // /** + // * Test for FAILURE + // */ + + // return $data; + // } + +} \ No newline at end of file diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php new file mode 100644 index 0000000000..7bd73bf3bb --- /dev/null +++ b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php @@ -0,0 +1,14 @@ +