diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index dba81aca..43c1435e 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -551,6 +551,7 @@ authorization_header_1: |- $client = new Client('http://127.0.0.1:7700', 'masterKey'); $client->getKeys(); tenant_token_guide_generate_sdk_1: |- + $uid = '85c3c2f9-bdd6-41f1-abd8-11fcf80e0f76'; $searchRules = (object) [ 'patient_medical_records' => (object) [ 'filter' => 'user_id = 1', @@ -561,7 +562,7 @@ tenant_token_guide_generate_sdk_1: |- 'expiresAt' => new DateTime('2025-12-20'), ]; - $token = $client->generateTenantToken($searchRules, $options); + $token = $client->generateTenantToken($uid, $searchRules, $options); tenant_token_guide_search_sdk_1: |- $frontEndClient = new Client('http://127.0.0.1:7700', $token); $frontEndClient->index('patient_medical_records')->search('blood test'); diff --git a/src/Delegates/HandlesSystem.php b/src/Delegates/HandlesSystem.php index e9e53175..c31e4737 100644 --- a/src/Delegates/HandlesSystem.php +++ b/src/Delegates/HandlesSystem.php @@ -32,8 +32,8 @@ public function stats(): array return $this->stats->show(); } - public function generateTenantToken($searchRules, ?array $options = []): string + public function generateTenantToken(string $uid, $searchRules, ?array $options = []): string { - return $this->tenantToken->generateTenantToken($searchRules, $options); + return $this->tenantToken->generateTenantToken($uid, $searchRules, $options); } } diff --git a/src/Endpoints/Keys.php b/src/Endpoints/Keys.php index 5aed8a83..ad7bf600 100644 --- a/src/Endpoints/Keys.php +++ b/src/Endpoints/Keys.php @@ -12,6 +12,8 @@ class Keys extends Endpoint { protected const PATH = '/keys'; + private ?string $uid; + private ?string $name; private ?string $key; private ?string $description; private ?array $actions; @@ -20,8 +22,10 @@ class Keys extends Endpoint private ?DateTime $createdAt; private ?DateTime $updatedAt; - public function __construct(Http $http, $key = null, $description = null, $actions = null, $indexes = null, $expiresAt = null, $createdAt = null, $updatedAt = null) + public function __construct(Http $http, $uid = null, $name = null, $key = null, $description = null, $actions = null, $indexes = null, $expiresAt = null, $createdAt = null, $updatedAt = null) { + $this->uid = $uid; + $this->name = $name; $this->key = $key; $this->description = $description; $this->actions = $actions; @@ -37,6 +41,8 @@ protected function newInstance(array $attributes): self { $key = new self( $this->http, + $attributes['uid'], + $attributes['name'], $attributes['key'], $attributes['description'], $attributes['actions'], @@ -60,6 +66,8 @@ protected function newInstance(array $attributes): self */ protected function fill(array $attributes): self { + $this->uid = $attributes['uid']; + $this->name = $attributes['name']; $this->key = $attributes['key']; $this->description = $attributes['description']; $this->actions = $attributes['actions']; @@ -93,6 +101,16 @@ protected function createDate($attribute): ?DateTime return false === $date ? null : $date; } + public function getUid(): ?string + { + return $this->uid; + } + + public function getName(): ?string + { + return $this->name; + } + public function getKey(): ?string { return $this->key; @@ -163,10 +181,8 @@ public function create(array $options = []): self public function update(string $key, array $options = []): self { - if ($options['expiresAt'] && $options['expiresAt'] instanceof DateTime) { - $options['expiresAt'] = $options['expiresAt']->format('Y-m-d\TH:i:s.vu\Z'); - } - $response = $this->http->patch(self::PATH.'/'.$key, $options); + $data = array_intersect_key($options, array_flip((array) ['description', 'name'])); + $response = $this->http->patch(self::PATH.'/'.$key, $data); return $this->fill($response); } diff --git a/src/Endpoints/TenantToken.php b/src/Endpoints/TenantToken.php index 4126f72a..4d64176c 100644 --- a/src/Endpoints/TenantToken.php +++ b/src/Endpoints/TenantToken.php @@ -36,7 +36,7 @@ private function validateTenantTokenArguments($searchRules, ?array $options = [] * - apiKey: The API key parent of the token. If you leave it empty the client API Key will be used. * - expiresAt: A DateTime when the key will expire. Note that if an expiresAt value is included it should be in UTC time. */ - public function generateTenantToken($searchRules, ?array $options = []): string + public function generateTenantToken(string $uid, $searchRules, ?array $options = []): string { if (!\array_key_exists('apiKey', $options) || '' == $options['apiKey']) { $options['apiKey'] = $this->apiKey; @@ -55,7 +55,7 @@ public function generateTenantToken($searchRules, ?array $options = []): string // Add the required fields to the payload $payload = []; - $payload['apiKeyPrefix'] = substr($options['apiKey'], 0, 8); + $payload['apiKeyUid'] = $uid; $payload['searchRules'] = $searchRules; if (\array_key_exists('expiresAt', $options)) { $payload['exp'] = $options['expiresAt']->getTimestamp(); diff --git a/tests/Endpoints/KeysAndPermissionsTest.php b/tests/Endpoints/KeysAndPermissionsTest.php index 6b25ac33..550d2df2 100644 --- a/tests/Endpoints/KeysAndPermissionsTest.php +++ b/tests/Endpoints/KeysAndPermissionsTest.php @@ -26,7 +26,7 @@ public function testGetKeysDefault(): void { $response = $this->client->getKeys(); - $this->assertCount(2, $response); + $this->assertGreaterThan(2, $response); $this->assertIsArray($response[0]->getActions()); $this->assertIsArray($response[0]->getIndexes()); $this->assertNull($response[0]->getExpiresAt()); @@ -38,7 +38,7 @@ public function testGetRawKeysDefault(): void { $response = $this->client->getRawKeys(); - $this->assertCount(2, $response['results']); + $this->assertGreaterThan(2, $response['results']); $this->assertArrayHasKey('actions', $response['results'][0]); $this->assertArrayHasKey('indexes', $response['results'][0]); $this->assertArrayHasKey('createdAt', $response['results'][0]); @@ -175,8 +175,6 @@ public function testUpdateKeyWithExpInString(): void $key = $this->client->createKey(self::INFO_KEY); $response = $this->client->updateKey($key->getKey(), [ 'description' => 'test update', - 'indexes' => ['*'], - 'expiresAt' => date('Y-m-d', strtotime('+1 day')), ]); $this->assertNotNull($response->getKey()); @@ -185,8 +183,8 @@ public function testUpdateKeyWithExpInString(): void $this->assertIsArray($response->getActions()); $this->assertSame($response->getActions(), self::INFO_KEY['actions']); $this->assertIsArray($response->getIndexes()); - $this->assertSame($response->getIndexes(), ['*']); - $this->assertNotNull($response->getExpiresAt()); + $this->assertSame($response->getIndexes(), ['index']); + $this->assertNull($response->getExpiresAt()); $this->assertNotNull($response->getCreatedAt()); $this->assertNotNull($response->getUpdatedAt()); @@ -235,35 +233,41 @@ public function testDateParsing(): void $httpClient = $this->createHttpClientMock(200, ' { "results": [ - { - "description": "test_key_1", - "key": "z1ySBsnp002e8bc6a31b794a95d623333be1fe4fd2d7eacdeaf7baf2c439866723e659ee", - "actions": ["*"], - "indexes": ["*"], - "expiresAt": "2023-06-14T10:34:03Z", - "createdAt": "2022-06-14T10:34:03Z", - "updatedAt": "2022-06-14T10:34:03Z" - }, - { - "description": "test_key_2", - "key": "z2ySBsnp002e8bc6a31b794a95d623333be1fe4fd2d7eacdeaf7baf2c439866723e659ee", - "actions": ["*"], - "indexes": ["*"], - "expiresAt": "2023-06-14T10:34:03.629Z", - "createdAt": "2022-06-14T10:34:03.627Z", - "updatedAt": "2022-06-14T10:34:03.627Z" - }, - { - "description": "test_key_3", - "key": "z3ySBsnp002e8bc6a31b794a95d623333be1fe4fd2d7eacdeaf7baf2c439866723e659ee", - "actions": ["*"], - "indexes": ["*"], - "expiresAt": "2023-06-14T10:34:03.629690014Z", - "createdAt": "2022-06-14T10:34:03.627606639Z", - "updatedAt": "2022-06-14T10:34:03.627606639Z" - } - ] - } + { + "description": "test_key_1", + "name": null, + "uid": "e3091e84-928c-44b5-8a61-7e5b15cd5009", + "key": "z1ySBsnp002e8bc6a31b794a95d623333be1fe4fd2d7eacdeaf7baf2c439866723e659ee", + "actions": ["*"], + "indexes": ["*"], + "expiresAt": "2023-06-14T10:34:03Z", + "createdAt": "2022-06-14T10:34:03Z", + "updatedAt": "2022-06-14T10:34:03Z" + }, + { + "description": "test_key_2", + "name": null, + "uid": "85f12b91-cf39-493a-9364-7d8b85b87798", + "key": "z2ySBsnp002e8bc6a31b794a95d623333be1fe4fd2d7eacdeaf7baf2c439866723e659ee", + "actions": ["*"], + "indexes": ["*"], + "expiresAt": "2023-06-14T10:34:03.629Z", + "createdAt": "2022-06-14T10:34:03.627Z", + "updatedAt": "2022-06-14T10:34:03.627Z" + }, + { + "description": "test_key_3", + "name": "test_key_3", + "uid": "6dffa3ee-b98f-4218-827a-7a062f23ebf5", + "key": "z3ySBsnp002e8bc6a31b794a95d623333be1fe4fd2d7eacdeaf7baf2c439866723e659ee", + "actions": ["*"], + "indexes": ["*"], + "expiresAt": "2023-06-14T10:34:03.629690014Z", + "createdAt": "2022-06-14T10:34:03.627606639Z", + "updatedAt": "2022-06-14T10:34:03.627606639Z" + } + ] + } '); $newClient = new \MeiliSearch\Client('https://localhost:7700', null, $httpClient); diff --git a/tests/Endpoints/TenantTokenTest.php b/tests/Endpoints/TenantTokenTest.php index 91975306..c2252d57 100644 --- a/tests/Endpoints/TenantTokenTest.php +++ b/tests/Endpoints/TenantTokenTest.php @@ -13,7 +13,7 @@ final class TenantTokenTest extends TestCase { - private string $privateKey; + private $key; private Client $privateClient; protected function setUp(): void @@ -22,20 +22,28 @@ protected function setUp(): void $this->createEmptyIndex('tenantToken'); $response = $this->client->getKeys(); - $this->privateKey = array_reduce($response, function ($carry, $item) { - if ($item->getDescription() && str_contains($item->getDescription(), 'Default Admin API')) { - return $item->getKey(); - } - }); + $this->key = $this->client->createKey([ + 'description' => 'tenant token key', + 'actions' => ['*'], + 'indexes' => ['*'], + 'expiresAt' => '2055-10-02T00:00:00Z' + ]); + + $this->privateKey = $this->key->getKey(); $this->privateClient = new Client($this->host, $this->privateKey); } + protected function tearDown(): void + { + $this->client->deleteKey($this->privateKey); + } + public function testGenerateTenantTokenWithSearchRulesOnly(): void { $promise = $this->client->index('tenantToken')->addDocuments(self::DOCUMENTS); $this->client->waitForTask($promise['taskUid']); - $token = $this->privateClient->generateTenantToken(['*']); + $token = $this->privateClient->generateTenantToken($this->key->getUid(), ['*']); $tokenClient = new Client($this->host, $token); $response = $tokenClient->index('tenantToken')->search(''); @@ -48,7 +56,7 @@ public function testGenerateTenantTokenWithSearchRulesAsObject(): void $promise = $this->client->index('tenantToken')->addDocuments(self::DOCUMENTS); $this->client->waitForTask($promise['taskUid']); - $token = $this->privateClient->generateTenantToken((object) ['*' => (object) []]); + $token = $this->privateClient->generateTenantToken($this->key->getUid(), (object) ['*' => (object) []]); $tokenClient = new Client($this->host, $token); $response = $tokenClient->index('tenantToken')->search(''); @@ -65,7 +73,7 @@ public function testGenerateTenantTokenWithFilter(): void ]); $this->client->waitForTask($promiseFromFilter['taskUid']); - $token = $this->privateClient->generateTenantToken((object) ['tenantToken' => (object) ['filter' => 'id > 10']]); + $token = $this->privateClient->generateTenantToken($this->key->getUid(), (object) ['tenantToken' => (object) ['filter' => 'id > 10']]); $tokenClient = new Client($this->host, $token); $response = $tokenClient->index('tenantToken')->search(''); @@ -77,7 +85,7 @@ public function testGenerateTenantTokenWithSearchRulesOnOneIndex(): void { $this->createEmptyIndex('tenantTokenDuplicate'); - $token = $this->privateClient->generateTenantToken(['tenantToken']); + $token = $this->privateClient->generateTenantToken($this->key->getUid(), ['tenantToken']); $tokenClient = new Client($this->host, $token); $response = $tokenClient->index('tenantToken')->search(''); @@ -93,7 +101,7 @@ public function testGenerateTenantTokenWithApiKey(): void 'apiKey' => $this->privateKey, ]; - $token = $this->client->generateTenantToken(['*'], $options); + $token = $this->client->generateTenantToken($this->key->getUid(), ['*'], $options); $tokenClient = new Client($this->host, $token); $response = $tokenClient->index('tenantToken')->search(''); @@ -109,7 +117,7 @@ public function testGenerateTenantTokenWithExpiresAt(): void 'expiresAt' => $tomorrow, ]; - $token = $this->privateClient->generateTenantToken(['*'], $options); + $token = $this->privateClient->generateTenantToken($this->key->getUid(), ['*'], $options); $tokenClient = new Client($this->host, $token); $response = $tokenClient->index('tenantToken')->search(''); @@ -119,7 +127,7 @@ public function testGenerateTenantTokenWithExpiresAt(): void public function testGenerateTenantTokenWithSearchRulesEmptyArray(): void { $this->expectException(InvalidArgumentException::class); - $this->privateClient->generateTenantToken([]); + $this->privateClient->generateTenantToken($this->key->getUid(), []); } public function testGenerateTenantTokenWithBadExpiresAt(): void @@ -133,7 +141,7 @@ public function testGenerateTenantTokenWithBadExpiresAt(): void 'expiresAt' => $yesterday, ]; - $this->privateClient->generateTenantToken(['*'], $options); + $this->privateClient->generateTenantToken($this->key->getUid(), ['*'], $options); } public function testGenerateTenantTokenWithNoApiKey(): void @@ -141,7 +149,7 @@ public function testGenerateTenantTokenWithNoApiKey(): void $client = new Client($this->host); $this->expectException(InvalidArgumentException::class); - $client->generateTenantToken(['*']); + $client->generateTenantToken($this->key->getUid(), ['*']); } public function testGenerateTenantTokenWithEmptyApiKey(): void @@ -149,6 +157,6 @@ public function testGenerateTenantTokenWithEmptyApiKey(): void $client = new Client($this->host); $this->expectException(InvalidArgumentException::class); - $client->generateTenantToken(['*'], ['apiKey' => '']); + $client->generateTenantToken($this->key->getUid(), ['*'], ['apiKey' => '']); } }