Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions app/controllers/api/projects.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Template\Template;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Response;
use PHPMailer\PHPMailer\PHPMailer;
use Utopia\Config\Config;
Expand Down Expand Up @@ -1094,12 +1095,15 @@
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
// TODO: When migrating to Platform API, mark keyId required for consistency
->param('keyId', 'unique()', new CustomId(), 'Key ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true)
->param('name', null, new Text(128), 'Key name. Max length: 128 chars.')
Comment thread
Meldiron marked this conversation as resolved.
->param('scopes', null, new Nullable(new ArrayList(new WhiteList(array_keys(Config::getParam('projectScopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE)), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.')
->param('expire', null, new Nullable(new DatetimeValidator()), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.', true)
->inject('response')
->inject('dbForPlatform')
->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForPlatform) {
->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForPlatform) {
$keyId = $keyId == 'unique()' ? ID::unique() : $keyId;

$project = $dbForPlatform->getDocument('projects', $projectId);

Expand All @@ -1108,7 +1112,7 @@
}

$key = new Document([
'$id' => ID::unique(),
'$id' => $keyId,
'$permissions' => [
Permission::read(Role::any()),
Comment thread
Meldiron marked this conversation as resolved.
Permission::update(Role::any()),
Expand Down
2 changes: 2 additions & 0 deletions tests/e2e/Scopes/ProjectCustom.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public function getProject(bool $fresh = false): array
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
'x-appwrite-project' => 'console',
], [
'keyId' => ID::unique(),
'name' => 'Demo Project Key',
'scopes' => [
'users.read',
Expand Down Expand Up @@ -194,6 +195,7 @@ public function getNewKey(array $scopes)
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
'x-appwrite-project' => 'console',
], [
'keyId' => ID::unique(),
'name' => 'Demo Project Key',
'scopes' => $scopes,
]);
Expand Down
60 changes: 58 additions & 2 deletions tests/e2e/Services/Projects/ProjectsConsoleClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2774,6 +2774,7 @@ public function testUpdateProjectServiceStatusServer($data): void
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
]), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['functions.read', 'teams.write'],
]);
Expand Down Expand Up @@ -3123,6 +3124,7 @@ public function testCreateProjectKey($data): array
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['teams.read', 'teams.write'],
]);
Expand All @@ -3138,6 +3140,52 @@ public function testCreateProjectKey($data): array
$this->assertArrayHasKey('accessedAt', $response['body']);
$this->assertEmpty($response['body']['accessedAt']);

/**
* Test for SUCCESS without key ID
*/
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'name' => 'Key Custom',
'scopes' => ['teams.read', 'teams.write'],
]);

$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);

/**
* Test for SUCCESS with custom ID
*/
$customKeyId = 'key-with-custom-id';
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => $customKeyId,
'name' => 'Key Custom',
'scopes' => ['teams.read', 'teams.write'],
]);

Comment thread
Meldiron marked this conversation as resolved.
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertSame($customKeyId, $response['body']['$id']);

/**
* Test for SUCCESS with magic string ID
*/
$response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => 'unique()',
'name' => 'Key Custom',
'scopes' => ['teams.read', 'teams.write'],
]);

$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertNotSame('unique()', $response['body']['$id']);

Comment thread
Meldiron marked this conversation as resolved.
$data = array_merge($data, [
'keyId' => $response['body']['$id'],
'secret' => $response['body']['secret']
Expand All @@ -3150,6 +3198,7 @@ public function testCreateProjectKey($data): array
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['unknown'],
]);
Expand All @@ -3174,7 +3223,7 @@ public function testListProjectKey($data): array


$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(1, $response['body']['total']);
$this->assertEquals(4, $response['body']['total']);

/**
* Test for FAILURE
Expand All @@ -3200,7 +3249,7 @@ public function testGetProjectKey($data): array
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals($keyId, $response['body']['$id']);
$this->assertEquals('Key Test', $response['body']['name']);
$this->assertEquals('Key Custom', $response['body']['name']);
$this->assertContains('teams.read', $response['body']['scopes']);
$this->assertContains('teams.write', $response['body']['scopes']);
$this->assertCount(2, $response['body']['scopes']);
Expand Down Expand Up @@ -3240,6 +3289,7 @@ public function testValidateProjectKey($data): void
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['users.write'],
'expire' => DateTime::addSeconds(new \DateTime(), 3600),
Expand All @@ -3260,6 +3310,7 @@ public function testValidateProjectKey($data): void
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['health.read'],
'expire' => null,
Expand All @@ -3282,6 +3333,7 @@ public function testValidateProjectKey($data): void
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['health.read'],
'expire' => DateTime::addSeconds(new \DateTime(), -3600),
Expand Down Expand Up @@ -3323,6 +3375,7 @@ public function testValidateProjectKey($data): void
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['teams.read'],
'expire' => DateTime::addSeconds(new \DateTime(), 3600),
Expand Down Expand Up @@ -3355,6 +3408,7 @@ public function testValidateProjectKey($data): void
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['health.read'],
'expire' => DateTime::addSeconds(new \DateTime(), 3600),
Expand Down Expand Up @@ -4364,6 +4418,7 @@ public function testDeleteSharedProject(): void
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['users.read', 'users.write'],
]);
Expand All @@ -4384,6 +4439,7 @@ public function testDeleteSharedProject(): void
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'keyId' => ID::unique(),
'name' => 'Key Test',
'scopes' => ['users.read', 'users.write'],
]);
Expand Down
Loading