Add E2E tests for dynamic keys

This commit is contained in:
Matej Bačo
2026-04-28 16:45:00 +02:00
parent 11f80fc2ed
commit 72dfd8a7bc
+131
View File
@@ -239,6 +239,112 @@ trait KeysBase
$this->deleteKey($customId);
}
// =========================================================================
// Create dynamic key tests
// =========================================================================
public function testCreateDynamicKey(): void
{
$key = $this->createDynamicKey(
['users.read', 'users.write'],
);
$this->assertSame(201, $key['headers']['status-code']);
$this->assertNotEmpty($key['body']['$id']);
$this->assertSame('', $key['body']['name']);
$this->assertSame(['users.read', 'users.write'], $key['body']['scopes']);
$this->assertNotEmpty($key['body']['secret']);
$this->assertStringStartsWith(API_KEY_DYNAMIC . '_', $key['body']['secret']);
$this->assertSame([], $key['body']['sdks']);
$this->assertNull($key['body']['accessedAt']);
$dateValidator = new DatetimeValidator();
$this->assertSame(true, $dateValidator->isValid($key['body']['$createdAt']));
$this->assertSame(true, $dateValidator->isValid($key['body']['$updatedAt']));
$this->assertSame(true, $dateValidator->isValid($key['body']['expire']));
// Verify JWT payload
$jwt = substr($key['body']['secret'], strlen(API_KEY_DYNAMIC . '_'));
$parts = explode('.', $jwt);
$this->assertCount(3, $parts);
$payload = json_decode(base64_decode(str_replace(['-', '_'], ['+', '/'], $parts[1])), true);
$this->assertNotEmpty($payload['projectId']);
$this->assertSame(['users.read', 'users.write'], $payload['scopes']);
// Verify default duration (900 seconds)
$expireDt = new \DateTime($key['body']['expire']);
$now = new \DateTime();
$diff = $expireDt->getTimestamp() - $now->getTimestamp();
$this->assertGreaterThanOrEqual(890, $diff);
$this->assertLessThanOrEqual(910, $diff);
}
public function testCreateDynamicKeyWithDuration(): void
{
$duration = 1800;
$key = $this->createDynamicKey(
['databases.read'],
$duration,
);
$this->assertSame(201, $key['headers']['status-code']);
$this->assertSame(['databases.read'], $key['body']['scopes']);
$expireDt = new \DateTime($key['body']['expire']);
$now = new \DateTime();
$diff = $expireDt->getTimestamp() - $now->getTimestamp();
$this->assertGreaterThanOrEqual($duration - 10, $diff);
$this->assertLessThanOrEqual($duration + 10, $diff);
}
public function testCreateDynamicKeyWithEmptyScopes(): void
{
$key = $this->createDynamicKey(
[],
);
$this->assertSame(201, $key['headers']['status-code']);
$this->assertSame([], $key['body']['scopes']);
}
public function testCreateDynamicKeyWithoutAuthentication(): void
{
$response = $this->createDynamicKey(
['users.read'],
null,
false
);
$this->assertSame(401, $response['headers']['status-code']);
}
public function testCreateDynamicKeyInvalidScope(): void
{
$response = $this->createDynamicKey(
['invalid.scope'],
);
$this->assertSame(400, $response['headers']['status-code']);
}
public function testCreateDynamicKeyInvalidDuration(): void
{
$response = $this->createDynamicKey(
['users.read'],
0,
);
$this->assertSame(400, $response['headers']['status-code']);
$response = $this->createDynamicKey(
['users.read'],
3601,
);
$this->assertSame(400, $response['headers']['status-code']);
}
// =========================================================================
// Update key tests
// =========================================================================
@@ -855,4 +961,29 @@ trait KeysBase
return $this->client->call(Client::METHOD_DELETE, '/project/keys/' . $keyId, $headers);
}
/**
* @param array<string> $scopes
*/
protected function createDynamicKey(array $scopes, ?int $duration = null, bool $authenticated = true): mixed
{
$params = [
'scopes' => $scopes,
];
if ($duration !== null) {
$params['duration'] = $duration;
}
$headers = [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
];
if ($authenticated) {
$headers = array_merge($headers, $this->getHeaders());
}
return $this->client->call(Client::METHOD_POST, '/project/keys/dynamic', $headers, $params);
}
}