Skip to content

Commit

Permalink
Adding some validations
Browse files Browse the repository at this point in the history
  • Loading branch information
alallema committed Feb 23, 2022
1 parent 75f6027 commit 81bee3f
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 34 deletions.
17 changes: 15 additions & 2 deletions src/Delegates/HandlesSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace MeiliSearch\Delegates;

use DateTime;
use MeiliSearch\Exceptions\InvalidArgumentException;
use MeiliSearch\Http\Serialize\Json;

trait HandlesSystem
Expand Down Expand Up @@ -39,8 +41,19 @@ public function base64url_encode($data)
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

public function generateTenantToken($searchRules, ?int $expiresAt = null, ?string $apiKey = null): string
public function generateTenantToken($searchRules, ?DateTime $expiresAt = null, ?string $apiKey = null): string
{
// Validate every fields
if (null == $apiKey && null == $this->apiKey) {
throw InvalidArgumentException::emptyArgument('api key');
}
if (null == $searchRules) {
throw InvalidArgumentException::emptyArgument('search rules');
}
if ($expiresAt && new DateTime() > $expiresAt) {
throw InvalidArgumentException::dateIsExpired($expiresAt);
}

$json = new Json();

// Standard JWT header for encryption with SHA256/HS256 algorithm
Expand All @@ -57,7 +70,7 @@ public function generateTenantToken($searchRules, ?int $expiresAt = null, ?strin
$payload['apiKeyPrefix'] = substr($apiKey, 0, 8);
$payload['searchRules'] = $searchRules;
if ($expiresAt) {
$payload['exp'] = $expiresAt;
$payload['exp'] = $expiresAt->getTimestamp();
}

// Serialize the Header
Expand Down
10 changes: 10 additions & 0 deletions src/Exceptions/InvalidArgumentException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace MeiliSearch\Exceptions;

use DateTime;
use Exception;

final class InvalidArgumentException extends Exception
Expand All @@ -25,4 +26,13 @@ public static function emptyArgument(string $argumentName): self
null
);
}

public static function dateIsExpired(DateTime $date): self
{
return new self(
sprintf('DateTime "%s" is expired. The date expiresAt should be in the future.', $date->format('Y-m-d H:i:s')),
400,
null
);
}
}
72 changes: 40 additions & 32 deletions tests/Endpoints/TenantTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

namespace Tests\Endpoints;

use DateTimeInterface;
use Tests\TestCase;
use Datetime;
use MeiliSearch\Client;
use MeiliSearch\Exceptions\ApiException;
use \Datetime;
use MeiliSearch\Exceptions\InvalidArgumentException;
use Tests\TestCase;

final class TenantTokenTest extends TestCase
{
Expand All @@ -18,9 +18,7 @@ final class TenantTokenTest extends TestCase
protected function setUp(): void
{
parent::setUp();
$index = $this->createEmptyIndex('tenantToken');
$promise = $index->addDocuments(self::DOCUMENTS);
$index->waitForTask($promise['uid']);
$this->createEmptyIndex('tenantToken');

$response = $this->client->getKeys();
$this->privateKey = array_reduce($response['results'], function ($carry, $item) {
Expand All @@ -33,7 +31,12 @@ protected function setUp(): void

public function testGenerateTenantTokenWithSearchRulesOnly(): void
{
$token = $this->privateClient->generateTenantToken(searchRules: array('*'));
$promise = $this->client->index('tenantToken')->addDocuments(self::DOCUMENTS);
$this->client->waitForTask($promise['uid']);

$token = $this->privateClient->generateTenantToken(
searchRules: ['*']
);
$tokenClient = new Client('http://127.0.0.1:7700', $token);
$response = $tokenClient->index('tenantToken')->search('');

Expand All @@ -46,9 +49,22 @@ public function testGenerateTenantTokenWithSearchRulesOnly(): void
$this->assertCount(7, $response->getHits());
}

public function testGenerateTenantTokenWithSearchRulesOnOneIndex(): void
{
$this->createEmptyIndex('tenantTokenDuplicate');
$token = $this->privateClient->generateTenantToken(searchRules: ['tenantToken']);
$tokenClient = new Client('http://127.0.0.1:7700', $token);
$response = $tokenClient->index('tenantToken')->search('');

$this->assertArrayHasKey('hits', $response->toArray());
$this->assertArrayHasKey('query', $response->toArray());
$this->expectException(ApiException::class);
$response = $tokenClient->index('tenantTokenDuplicate')->search('');
}

public function testGenerateTenantTokenWithApiKey(): void
{
$token = $this->client->generateTenantToken(searchRules: array('*'), apiKey: $this->privateKey);
$token = $this->client->generateTenantToken(searchRules: ['*'], apiKey: $this->privateKey);
$tokenClient = new Client('http://127.0.0.1:7700', $token);
$response = $tokenClient->index('tenantToken')->search('');

Expand All @@ -57,16 +73,14 @@ public function testGenerateTenantTokenWithApiKey(): void
$this->assertArrayHasKey('limit', $response->toArray());
$this->assertArrayHasKey('processingTimeMs', $response->toArray());
$this->assertArrayHasKey('query', $response->toArray());
$this->assertSame(7, $response->getNbHits());
$this->assertCount(7, $response->getHits());
}

public function testGenerateTenantTokenWithExpiresAt(): void
{
$date = new DateTime();
$tomorrow = $date->modify('+1 day')->getTimestamp();
$tomorrow = $date->modify('+1 day');

$token = $this->privateClient->generateTenantToken(searchRules: array('*'), expiresAt: $tomorrow);
$token = $this->privateClient->generateTenantToken(searchRules: ['*'], expiresAt: $tomorrow);
$tokenClient = new Client('http://127.0.0.1:7700', $token);
$response = $tokenClient->index('tenantToken')->search('');

Expand All @@ -75,39 +89,33 @@ public function testGenerateTenantTokenWithExpiresAt(): void
$this->assertArrayHasKey('limit', $response->toArray());
$this->assertArrayHasKey('processingTimeMs', $response->toArray());
$this->assertArrayHasKey('query', $response->toArray());
$this->assertSame(7, $response->getNbHits());
$this->assertCount(7, $response->getHits());
}


public function testGenerateTenantTokenWithoutSearchRules(): void
public function testGenerateTenantTokenWithEmptySearchRules(): void
{
$this->expectException(InvalidArgumentException::class);
$token = $this->privateClient->generateTenantToken(searchRules: '');
$tokenClient = new Client('http://127.0.0.1:7700', $token);

$this->expectException(ApiException::class);
$tokenClient->index('tenantToken')->search('');
}


public function testGenerateTenantTokenWithMasterKey(): void
public function testGenerateTenantTokenWithSearchRulesEmptyArray(): void
{
$token = $this->client->generateTenantToken(array('*'));
$tokenClient = new Client('http://127.0.0.1:7700', $token);

$this->expectException(ApiException::class);
$tokenClient->index('tenantToken')->search('');
$this->expectException(InvalidArgumentException::class);
$token = $this->privateClient->generateTenantToken(searchRules: []);
}

public function testGenerateTenantTokenWithBadExpiresAt(): void
{
$date = new DateTime();
$yesterday = $date->modify('-2 day')->getTimestamp();
$yesterday = $date->modify('-1 day');

$token = $this->privateClient->generateTenantToken(searchRules: array('*'), expiresAt: $yesterday);
$tokenClient = new Client('http://127.0.0.1:7700', $token);
$this->expectException(InvalidArgumentException::class);
$token = $this->privateClient->generateTenantToken(searchRules: ['*'], expiresAt: $yesterday);
}

$this->expectException(ApiException::class);
$tokenClient->index('tenantToken')->search('');
public function testGenerateTenantTokenWithNoApiKey(): void
{
$client = new Client($this->host);
$this->expectException(InvalidArgumentException::class);
$token = $client->generateTenantToken(searchRules: ['*']);
}
}

0 comments on commit 81bee3f

Please sign in to comment.