chore: make devkeys test dependence free

This commit is contained in:
Chirag Aggarwal
2025-04-14 18:01:40 +00:00
parent 74abf4897b
commit 6596569259
4 changed files with 635 additions and 531 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ _APP_SYSTEM_TEAM_EMAIL=team@appwrite.io
_APP_EMAIL_SECURITY=security@appwrite.io
_APP_EMAIL_CERTIFICATES=certificates@appwrite.io
_APP_SYSTEM_RESPONSE_FORMAT=
_APP_OPTIONS_ABUSE=disabled
_APP_OPTIONS_ABUSE=enabled
_APP_OPTIONS_ROUTER_PROTECTION=disabled
_APP_OPTIONS_FORCE_HTTPS=disabled
_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled
@@ -2,6 +2,48 @@
namespace Tests\E2E\Services\Projects;
use Tests\E2E\Client;
use Utopia\Database\Helpers\ID;
trait ProjectsBase
{
protected function setupProject(mixed $params): string
{
$team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => ID::unique(),
'name' => 'Project Test',
]);
$this->assertEquals(201, $team['headers']['status-code'], 'Setup team failed with status code: ' . $team['headers']['status-code'] . ' and response: ' . json_encode($team['body'], JSON_PRETTY_PRINT));
$project = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
...$params,
'teamId' => $team['body']['$id'],
]);
$this->assertEquals(201, $project['headers']['status-code'], 'Setup project failed with status code: ' . $project['headers']['status-code'] . ' and response: ' . json_encode($project['body'], JSON_PRETTY_PRINT));
return $project['body']['$id'];
}
protected function setupDevKey(mixed $params): array
{
$devKey = $this->client->call(Client::METHOD_POST, '/projects/' . $params['projectId'] . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), $params);
$this->assertEquals(201, $devKey['headers']['status-code'], 'Setup devKey failed with status code: ' . $devKey['headers']['status-code'] . ' and response: ' . json_encode($devKey['body'], JSON_PRETTY_PRINT));
return [
'$id' => $devKey['body']['$id'],
'secret' => $devKey['body']['secret'],
];
}
}
@@ -22,7 +22,6 @@ class ProjectsConsoleClientTest extends Scope
use ProjectConsole;
use SideClient;
use Async;
use ProjectsDevKeys;
/**
* @group devKeys
@@ -4241,4 +4240,596 @@ class ProjectsConsoleClientTest extends Scope
return $data;
}
/**
* Devkeys Tests starts here ------------------------------------------------
*/
/**
* @group devKeys
*/
public function testCreateProjectDevKey(): void
{
/**
* Test for SUCCESS
*/
$id = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testCreateProjectDevKey',
'region' => System::getEnv('_APP_REGION', 'default')
]);
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals('Key Test', $response['body']['name']);
$this->assertNotEmpty($response['body']['secret']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);
/** Create a second dev key */
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals('Dev Key Test', $response['body']['name']);
$this->assertNotEmpty($response['body']['secret']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);
/**
* Test for FAILURE
*/
/** TEST expiry date is required */
$res = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test'
]);
$this->assertEquals(400, $res['headers']['status-code']);
}
/**
* @group devKeys
*/
public function testListProjectDevKey(): void
{
/**
* Test for SUCCESS
*/
$projectId = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testListProjectDevKey',
'region' => System::getEnv('_APP_REGION', 'default')
]);
/** Create devKey 1 */
$this->setupDevKey([
'projectId' => $projectId,
'name' => 'Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
/** Create devKey 2 */
$this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
/** List all dev keys */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(2, $response['body']['total']);
/** List dev keys with limit */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::limit(1)->toString()
]
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(1, $response['body']['total']);
/** List dev keys with search */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'search' => 'Dev'
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(1, $response['body']['total']);
$this->assertEquals('Dev Key Test', $response['body']['devKeys'][0]['name']);
/** List dev keys with querying `expire` */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [Query::lessThan('expire', (new \DateTime())->format('Y-m-d H:i:s'))->toString()]
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(0, $response['body']['total']); // No dev keys expired
/**
* Test for FAILURE
*/
/** Test for search with invalid query */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::search('name', 'Invalid')->toString()
]
]);
$this->assertEquals(400, $response['headers']['status-code']);
$this->assertEquals('Invalid `queries` param: Invalid query: Attribute not found in schema: name', $response['body']['message']);
}
/**
* @group devKeys
*/
public function testGetProjectDevKey(): void
{
/**
* Test for SUCCESS
*/
$projectId = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testGetProjectDevKey',
'region' => System::getEnv('_APP_REGION', 'default')
]);
$devKey = $this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals($devKey['$id'], $response['body']['$id']);
$this->assertEquals('Dev Key Test', $response['body']['name']);
$this->assertNotEmpty($response['body']['secret']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);
/**
* Test for FAILURE
*/
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/error', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(404, $response['headers']['status-code']);
}
/**
* @group devKeys
*/
public function testGetDevKeyWithSdks(): void
{
/**
* Test for SUCCESS
*/
$projectId = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testGetDevKeyWithSdks',
'region' => System::getEnv('_APP_REGION', 'default')
]);
$devKey = $this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
/** Use dev key with python sdk */
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret'],
'x-sdk-name' => 'python'
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $res['headers']['status-code']);
/** Use dev key with php sdk */
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret'],
'x-sdk-name' => 'php'
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $res['headers']['status-code']);
/** Get the dev key */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertArrayHasKey('sdks', $response['body']);
$this->assertCount(2, $response['body']['sdks']);
$this->assertContains('python', $response['body']['sdks']);
$this->assertContains('php', $response['body']['sdks']);
}
/**
* @group devKeys
*/
public function testNoHostValidationWithDevKey(): void
{
/**
* Test for SUCCESS
*/
$projectId = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testNoHostValidationWithDevKey',
'region' => System::getEnv('_APP_REGION', 'default')
]);
$devKey = $this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
/** Test oauth2 and get invalid `success` URL */
$response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/google', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], [
'success' => 'https://example.com',
'failure' => 'https://example.com'
]);
$this->assertEquals(400, $response['headers']['status-code']);
$this->assertEquals('Invalid `success` param: URL host must be one of: localhost, appwrite.io, *.appwrite.io', $response['body']['message']);
/** Test oauth2 with devKey and now get oauth2 is disabled */
$response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/google', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret']
], [
'success' => 'https://example.com',
'failure' => 'https://example.com'
]);
$this->assertEquals(412, $response['headers']['status-code']);
$this->assertEquals('This provider is disabled. Please enable the provider from your Appwrite console to continue.', $response['body']['message']);
/** Test hostname in Magic URL */
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], [
'userId' => ID::unique(),
'email' => 'user@appwrite.io',
'url' => 'https://example.com',
]);
$this->assertEquals(400, $response['headers']['status-code']);
$this->assertEquals('Invalid `url` param: URL host must be one of: localhost, appwrite.io, *.appwrite.io', $response['body']['message']);
/** Test hostname in Magic URL with devKey */
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret']
], [
'userId' => ID::unique(),
'email' => 'user@appwrite.io',
'url' => 'https://example.com',
]);
$this->assertEquals(201, $response['headers']['status-code']);
}
/**
* @group devKeys
*/
public function testCorsWithDevKey(): void
{
/**
* Test for SUCCESS
*/
$projectId = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testCorsWithDevKey',
'region' => System::getEnv('_APP_REGION', 'default')
]);
$devKey = $this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
$origin = 'http://example.com';
/**
* Test CORS without Dev Key (should fail due to origin)
*/
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'origin' => $origin,
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(403, $response['headers']['status-code']);
$this->assertNotEquals($origin, $response['headers']['access-control-allow-origin'] ?? null);
$this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin'] ?? null);
/**
* Test CORS with Dev Key (should bypass origin check)
*/
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'origin' => $origin,
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $response['headers']['status-code']);
$this->assertEquals('*', $response['headers']['access-control-allow-origin'] ?? null);
}
/**
* @group devKeys
*/
public function testNoRateLimitWithDevKey(): void
{
/**
* Test for SUCCESS
*/
$projectId = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testNoRateLimitWithDevKey',
'region' => System::getEnv('_APP_REGION', 'default')
]);
$devKey = $this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
/**
* Test for SUCCESS
*/
for ($i = 0; $i < 10; $i++) {
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $response['headers']['status-code']);
}
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(429, $response['headers']['status-code']);
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $response['headers']['status-code']);
/**
* Test for FAILURE
*/
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $projectId . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), -3600),
]);
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $response['body']['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(429, $response['headers']['status-code']);
/**
* Test for FAILURE after expire
*/
$devKey = $this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test Expire 5 seconds',
'expire' => DateTime::addSeconds(new \DateTime(), 5)
]);
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $response['headers']['status-code']);
sleep(5);
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(429, $response['headers']['status-code']);
}
/**
* @group devKeys
*/
public function testUpdateProjectDevKey(): void
{
$projectId = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testUpdateProjectDevKey',
'region' => System::getEnv('_APP_REGION', 'default')
]);
$devKey = $this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
$response = $this->client->call(Client::METHOD_PUT, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test Update',
'expire' => DateTime::addSeconds(new \DateTime(), 360),
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals($devKey['$id'], $response['body']['$id']);
$this->assertEquals('Key Test Update', $response['body']['name']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals($devKey['$id'], $response['body']['$id']);
$this->assertEquals('Key Test Update', $response['body']['name']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);
}
/**
* @group devKeys
*/
public function testDeleteProjectDevKey(): void
{
$projectId = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testDeleteProjectDevKey',
'region' => System::getEnv('_APP_REGION', 'default')
]);
$devKey = $this->setupDevKey([
'projectId' => $projectId,
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
$response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], 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']);
/**
* Get rate limit trying to use the deleted key
*/
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(429, $response['headers']['status-code']);
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId . '/dev-keys/' . $devKey['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(404, $response['headers']['status-code']);
/**
* Test for FAILURE
*/
$response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId . '/dev-keys/error', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(404, $response['headers']['status-code']);
}
/**
* Devkeys Tests ends here ------------------------------------------------
*/
}
@@ -1,529 +0,0 @@
<?php
namespace Tests\E2E\Services\Projects;
use Tests\E2E\Client;
use Utopia\Database\DateTime;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
trait ProjectsDevKeys
{
/**
* @depends testCreateProject
* @group devKeys
*/
public function testCreateProjectDevKey($data): array
{
/**
* Test for SUCCESS
*/
$id = $data['projectId'] ?? '';
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals('Key Test', $response['body']['name']);
$this->assertNotEmpty($response['body']['secret']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);
/** Create a second dev key */
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Dev Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 36000)
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals('Dev Key Test', $response['body']['name']);
$this->assertNotEmpty($response['body']['secret']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);
/**
* Test for FAILURE
*/
/** TEST expiry date is required */
$res = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test'
]);
$this->assertEquals(400, $res['headers']['status-code']);
$data = array_merge($data, [
'keyId' => $response['body']['$id'],
'secret' => $response['body']['secret']
]);
return $data;
}
/**
* @depends testCreateProjectDevKey
* @group devKeys
*/
public function testListProjectDevKey($data): array
{
/**
* Test for SUCCESS
*/
/** List all dev keys */
$id = $data['projectId'] ?? '';
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(2, $response['body']['total']);
/** List dev keys with limit */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::limit(1)->toString()
]
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(1, $response['body']['total']);
/** List dev keys with search */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'search' => 'Dev'
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(1, $response['body']['total']);
$this->assertEquals('Dev Key Test', $response['body']['devKeys'][0]['name']);
/** List dev keys with querying `expire` */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [Query::lessThan('expire', (new \DateTime())->format('Y-m-d H:i:s'))->toString()]
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(0, $response['body']['total']); // No dev keys expired
/**
* Test for FAILURE
*/
/** Test for search with invalid query */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::search('name', 'Invalid')->toString()
]
]);
$this->assertEquals(400, $response['headers']['status-code']);
$this->assertEquals('Invalid `queries` param: Invalid query: Attribute not found in schema: name', $response['body']['message']);
return $data;
}
/**
* @depends testCreateProjectDevKey
* @group devKeys
*/
public function testGetProjectDevKey($data): array
{
/**
* Test for SUCCESS
*/
$id = $data['projectId'] ?? '';
$keyId = $data['keyId'] ?? '';
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys/' . $keyId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals($keyId, $response['body']['$id']);
$this->assertEquals('Dev Key Test', $response['body']['name']);
$this->assertNotEmpty($response['body']['secret']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);
/**
* Test for FAILURE
*/
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys/error', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(404, $response['headers']['status-code']);
return $data;
}
/**
* @depends testCreateProjectDevKey
* @group devKeys
*/
public function testGetDevKeyWithSdks($data): array
{
$id = $data['projectId'] ?? '';
$keyId = $data['keyId'] ?? '';
$devKey = $data['secret'] ?? '';
/** Use dev key with python sdk */
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $devKey,
'x-sdk-name' => 'python'
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $res['headers']['status-code']);
/** Use dev key with php sdk */
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $devKey,
'x-sdk-name' => 'php'
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $res['headers']['status-code']);
/** Get the dev key */
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys/' . $keyId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertArrayHasKey('sdks', $response['body']);
$this->assertCount(2, $response['body']['sdks']);
$this->assertContains('python', $response['body']['sdks']);
$this->assertContains('php', $response['body']['sdks']);
return $data;
}
/**
* @depends testCreateProjectDevKey
* @group devKeys
*/
public function testNoHostValidationWithDevKey($data): void
{
$id = $data['projectId'] ?? '';
$devKey = $data['secret'] ?? '';
/** Test oauth2 and get invalid `success` URL */
$response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/google', [
'content-type' => 'application/json',
'x-appwrite-project' => $id
], [
'success' => 'https://example.com',
'failure' => 'https://example.com'
]);
$this->assertEquals(400, $response['headers']['status-code']);
$this->assertEquals('Invalid `success` param: URL host must be one of: localhost, appwrite.io, *.appwrite.io', $response['body']['message']);
/** Test oauth2 with devKey and now get oauth2 is disabled */
$response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/google', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $devKey
], [
'success' => 'https://example.com',
'failure' => 'https://example.com'
]);
$this->assertEquals(412, $response['headers']['status-code']);
$this->assertEquals('This provider is disabled. Please enable the provider from your Appwrite console to continue.', $response['body']['message']);
/** Test hostname in Magic URL */
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
], [
'userId' => ID::unique(),
'email' => 'user@appwrite.io',
'url' => 'https://example.com',
]);
$this->assertEquals(400, $response['headers']['status-code']);
$this->assertEquals('Invalid `url` param: URL host must be one of: localhost, appwrite.io, *.appwrite.io', $response['body']['message']);
/** Test hostname in Magic URL with devKey */
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $devKey
], [
'userId' => ID::unique(),
'email' => 'user@appwrite.io',
'url' => 'https://example.com',
]);
$this->assertEquals(201, $response['headers']['status-code']);
}
/**
* @depends testCreateProjectDevKey
* @group devKeys
*/
public function testCorsWithDevKey($data): void
{
$projectId = $data['projectId'] ?? '';
$devKey = $data['secret'] ?? '';
$origin = 'http://example.com';
/**
* Test CORS without Dev Key (should fail due to origin)
*/
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'origin' => $origin,
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(403, $response['headers']['status-code']);
$this->assertNotEquals($origin, $response['headers']['access-control-allow-origin'] ?? null);
$this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin'] ?? null);
/**
* Test CORS with Dev Key (should bypass origin check)
*/
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'origin' => $origin,
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-dev-key' => $devKey
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $response['headers']['status-code']);
$this->assertEquals('*', $response['headers']['access-control-allow-origin'] ?? null);
}
/**
* @depends testCreateProjectDevKey
* @group devKeys
*/
public function testNoRateLimitWithDevKey($data): void
{
$id = $data['projectId'] ?? '';
$devKey = $data['secret'] ?? '';
/**
* Test for SUCCESS
*/
for ($i = 0; $i < 10; $i++) {
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $res['headers']['status-code']);
}
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(429, $res['headers']['status-code']);
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $devKey
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $res['headers']['status-code']);
/**
* Test for FAILURE
*/
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), -3600),
]);
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $response['body']['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(429, $res['headers']['status-code']);
/**
* Test for FAILURE after expire
*/
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test',
'expire' => DateTime::addSeconds(new \DateTime(), 5),
]);
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $response['body']['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(401, $res['headers']['status-code']);
sleep(5);
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $response['body']['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(429, $res['headers']['status-code']);
}
/**
* @depends testCreateProjectDevKey
* @group devKeys
*/
public function testUpdateProjectDevKey($data): array
{
$id = $data['projectId'] ?? '';
$keyId = $data['keyId'] ?? '';
$response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/dev-keys/' . $keyId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Test Update',
'expire' => DateTime::addSeconds(new \DateTime(), 360),
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals($keyId, $response['body']['$id']);
$this->assertEquals('Key Test Update', $response['body']['name']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertNotEmpty($response['body']['accessedAt']);
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys/' . $keyId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals($keyId, $response['body']['$id']);
$this->assertEquals('Key Test Update', $response['body']['name']);
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertNotEmpty($response['body']['accessedAt']);
return $data;
}
/**
* @depends testCreateProjectDevKey
* @group devKeys
*/
public function testDeleteProjectDevKey($data): array
{
$id = $data['projectId'] ?? '';
$keyId = $data['keyId'] ?? '';
$response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/dev-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']);
/**
* Get rate limit trying to use the deleted key
*/
$res = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => $id,
'x-appwrite-dev-key' => $data['secret']
], [
'email' => 'user@appwrite.io',
'password' => 'password'
]);
$this->assertEquals(429, $res['headers']['status-code']);
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/dev-keys/' . $keyId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(404, $response['headers']['status-code']);
/**
* Test for FAILURE
*/
$response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/dev-keys/error', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(404, $response['headers']['status-code']);
return $data;
}
}