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
3 changes: 2 additions & 1 deletion .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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');
4 changes: 2 additions & 2 deletions src/Delegates/HandlesSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
26 changes: 21 additions & 5 deletions src/Endpoints/Keys.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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'],
Expand All @@ -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'];
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Endpoints/TenantToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like suggested in this [comment]
(meilisearch/meilisearch-python#484 (review)) it could be good to rename uid to api_key_uid

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @alallema I'll apply this suggestion in a next PR, btw I will do it in the dart as well :)

{
if (!\array_key_exists('apiKey', $options) || '' == $options['apiKey']) {
$options['apiKey'] = $this->apiKey;
Expand All @@ -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();
Expand Down
74 changes: 39 additions & 35 deletions tests/Endpoints/KeysAndPermissionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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]);
Expand Down Expand Up @@ -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());
Expand All @@ -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());

Expand Down Expand Up @@ -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);
Expand Down
40 changes: 24 additions & 16 deletions tests/Endpoints/TenantTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

final class TenantTokenTest extends TestCase
{
private string $privateKey;
private $key;
private Client $privateClient;

protected function setUp(): void
Expand All @@ -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('');

Expand All @@ -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('');

Expand All @@ -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('');

Expand All @@ -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('');

Expand All @@ -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('');

Expand All @@ -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('');

Expand All @@ -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
Expand All @@ -133,22 +141,22 @@ public function testGenerateTenantTokenWithBadExpiresAt(): void
'expiresAt' => $yesterday,
];

$this->privateClient->generateTenantToken(['*'], $options);
$this->privateClient->generateTenantToken($this->key->getUid(), ['*'], $options);
}

public function testGenerateTenantTokenWithNoApiKey(): void
{
$client = new Client($this->host);

$this->expectException(InvalidArgumentException::class);
$client->generateTenantToken(['*']);
$client->generateTenantToken($this->key->getUid(), ['*']);
}

public function testGenerateTenantTokenWithEmptyApiKey(): void
{
$client = new Client($this->host);

$this->expectException(InvalidArgumentException::class);
$client->generateTenantToken(['*'], ['apiKey' => '']);
$client->generateTenantToken($this->key->getUid(), ['*'], ['apiKey' => '']);
}
}