From a254d6ab58ca881ac81bb5562a46b923591e54ac Mon Sep 17 00:00:00 2001 From: alallema Date: Thu, 23 Jun 2022 17:00:23 +0200 Subject: [PATCH 01/12] Add uid to the generateTenantToken method --- meilisearch/client.py | 17 ++++++++++++++++- tests/client/test_client_tenant_token.py | 24 +++++++++++++++--------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/meilisearch/client.py b/meilisearch/client.py index 0354bdac..0890d110 100644 --- a/meilisearch/client.py +++ b/meilisearch/client.py @@ -1,3 +1,4 @@ +import re import base64 import hashlib import hmac @@ -5,6 +6,7 @@ import datetime from urllib import parse from typing import Any, Dict, List, Optional, Union +from xmlrpc.client import Boolean from meilisearch.index import Index from meilisearch.config import Config from meilisearch.task import get_task, get_tasks, wait_for_task @@ -473,6 +475,7 @@ def wait_for_task( def generate_tenant_token( self, + uid: str, search_rules: Union[Dict[str, Any], List[str]], *, expires_at: Optional[datetime.datetime] = None, @@ -482,6 +485,8 @@ def generate_tenant_token( Parameters ---------- + uid: + The uid of the API key used as issuer of the token. search_rules: A Dictionary or list of string which contains the rules to be enforced at search time for all or specific accessible indexes for the signing API Key. @@ -501,6 +506,8 @@ def generate_tenant_token( # Validate all fields if api_key == '' or api_key is None and self.config.api_key is None: raise Exception('An api key is required in the client or should be passed as an argument.') + if uid == '' or uid is None or self._valid_uuid(uid) is False: + raise Exception('An uid is required and must comply to the uuid4 format.') if not search_rules or search_rules == ['']: raise Exception('The search_rules field is mandatory and should be defined.') if expires_at and expires_at < datetime.datetime.utcnow(): @@ -516,7 +523,7 @@ def generate_tenant_token( # Add the required fields to the payload payload = { - 'apiKeyPrefix': api_key[0:8], + 'apiKeyUid': uid, 'searchRules': search_rules, 'exp': int(datetime.datetime.timestamp(expires_at)) if expires_at is not None else None } @@ -542,3 +549,11 @@ def _base64url_encode( data: bytes ) -> str: return base64.urlsafe_b64encode(data).decode('utf-8').replace('=','') + + @staticmethod + def _valid_uuid( + uuid: str + ) -> bool: + uuid4hex = re.compile(r'^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}', re.I) + match = uuid4hex.match(uuid) + return bool(match) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index d90c5335..a696863b 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -12,7 +12,7 @@ def test_generate_tenant_token_with_search_rules(get_private_key, index_with_doc index_with_documents() client = meilisearch.Client(BASE_URL, get_private_key['key']) - token = client.generate_tenant_token(search_rules=["*"]) + token = client.generate_tenant_token(uid=get_private_key['uid'], search_rules=["*"]) token_client = meilisearch.Client(BASE_URL, token) response = token_client.index('indexUID').search('', { @@ -28,7 +28,7 @@ def test_generate_tenant_token_with_search_rules_on_one_index(get_private_key, e empty_index('tenant_token') client = meilisearch.Client(BASE_URL, get_private_key['key']) - token = client.generate_tenant_token(search_rules=['indexUID']) + token = client.generate_tenant_token(uid=get_private_key['uid'], search_rules=['indexUID']) token_client = meilisearch.Client(BASE_URL, token) response = token_client.index('indexUID').search('') @@ -40,7 +40,7 @@ def test_generate_tenant_token_with_search_rules_on_one_index(get_private_key, e def test_generate_tenant_token_with_api_key(client, get_private_key, empty_index): """Tests create a tenant token with search rules and an api key.""" empty_index() - token = client.generate_tenant_token(search_rules=["*"], api_key=get_private_key['key']) + token = client.generate_tenant_token(uid=get_private_key['uid'], search_rules=["*"], api_key=get_private_key['key']) token_client = meilisearch.Client(BASE_URL, token) response = token_client.index('indexUID').search('') @@ -53,7 +53,7 @@ def test_generate_tenant_token_with_expires_at(client, get_private_key, empty_in client = meilisearch.Client(BASE_URL, get_private_key['key']) tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1) - token = client.generate_tenant_token(search_rules=["*"], expires_at=tomorrow) + token = client.generate_tenant_token(uid=get_private_key['uid'], search_rules=["*"], expires_at=tomorrow) token_client = meilisearch.Client(BASE_URL, token) response = token_client.index('indexUID').search('') @@ -65,28 +65,28 @@ def test_generate_tenant_token_with_empty_search_rules_in_list(get_private_key): client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(search_rules=['']) + client.generate_tenant_token(uid=get_private_key['uid'], search_rules=['']) def test_generate_tenant_token_without_search_rules_in_list(get_private_key): """Tests create a tenant token without search rules.""" client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(search_rules=[]) + client.generate_tenant_token(uid=get_private_key['uid'], search_rules=[]) def test_generate_tenant_token_without_search_rules_in_dict(get_private_key): """Tests create a tenant token without search rules.""" client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(search_rules={}) + client.generate_tenant_token(uid=get_private_key['uid'], search_rules={}) def test_generate_tenant_token_with_empty_search_rules_in_dict(get_private_key): """Tests create a tenant token without search rules.""" client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(search_rules={''}) + client.generate_tenant_token(uid=get_private_key['uid'], search_rules={''}) def test_generate_tenant_token_with_bad_expires_at(client, get_private_key): """Tests create a tenant token with a bad expires at.""" @@ -95,7 +95,7 @@ def test_generate_tenant_token_with_bad_expires_at(client, get_private_key): yesterday = datetime.datetime.utcnow() + datetime.timedelta(days=-1) with pytest.raises(Exception): - client.generate_tenant_token(search_rules=["*"], expires_at=yesterday) + client.generate_tenant_token(uid=get_private_key['uid'], search_rules=["*"], expires_at=yesterday) def test_generate_tenant_token_with_no_api_key(client): """Tests create a tenant token with no api key.""" @@ -104,3 +104,9 @@ def test_generate_tenant_token_with_no_api_key(client): with pytest.raises(Exception): client.generate_tenant_token(search_rules=["*"]) +def test_generate_tenant_token_with_no_uid(client, get_private_key): + """Tests create a tenant token with no uid.""" + client = meilisearch.Client(BASE_URL, get_private_key['key']) + + with pytest.raises(Exception): + client.generate_tenant_token(uid=None, search_rules=["*"]) From 93af29a6300fe1e3bee2a46d5b37f3b7059afc01 Mon Sep 17 00:00:00 2001 From: alallema Date: Mon, 27 Jun 2022 09:47:36 +0200 Subject: [PATCH 02/12] Replace uid by api_key_uid --- meilisearch/client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/meilisearch/client.py b/meilisearch/client.py index 0890d110..f13c7818 100644 --- a/meilisearch/client.py +++ b/meilisearch/client.py @@ -475,7 +475,7 @@ def wait_for_task( def generate_tenant_token( self, - uid: str, + api_key_uid: str, search_rules: Union[Dict[str, Any], List[str]], *, expires_at: Optional[datetime.datetime] = None, @@ -485,7 +485,7 @@ def generate_tenant_token( Parameters ---------- - uid: + api_key_uid: The uid of the API key used as issuer of the token. search_rules: A Dictionary or list of string which contains the rules to be enforced at search time for all or specific @@ -506,7 +506,7 @@ def generate_tenant_token( # Validate all fields if api_key == '' or api_key is None and self.config.api_key is None: raise Exception('An api key is required in the client or should be passed as an argument.') - if uid == '' or uid is None or self._valid_uuid(uid) is False: + if api_key_uid == '' or api_key_uid is None or self._valid_uuid(api_key_uid) is False: raise Exception('An uid is required and must comply to the uuid4 format.') if not search_rules or search_rules == ['']: raise Exception('The search_rules field is mandatory and should be defined.') @@ -523,7 +523,7 @@ def generate_tenant_token( # Add the required fields to the payload payload = { - 'apiKeyUid': uid, + 'apiKeyUid': api_key_uid, 'searchRules': search_rules, 'exp': int(datetime.datetime.timestamp(expires_at)) if expires_at is not None else None } From 2b38a302573a318c9e969904e02a2c78db304f12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:12 +0200 Subject: [PATCH 03/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index a696863b..ed2a0e03 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -12,7 +12,7 @@ def test_generate_tenant_token_with_search_rules(get_private_key, index_with_doc index_with_documents() client = meilisearch.Client(BASE_URL, get_private_key['key']) - token = client.generate_tenant_token(uid=get_private_key['uid'], search_rules=["*"]) + token = client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules=["*"]) token_client = meilisearch.Client(BASE_URL, token) response = token_client.index('indexUID').search('', { From 523c66127670a315283f74a1e40d1a73d5b9ea99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:17 +0200 Subject: [PATCH 04/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index ed2a0e03..5643d58e 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -28,7 +28,7 @@ def test_generate_tenant_token_with_search_rules_on_one_index(get_private_key, e empty_index('tenant_token') client = meilisearch.Client(BASE_URL, get_private_key['key']) - token = client.generate_tenant_token(uid=get_private_key['uid'], search_rules=['indexUID']) + token = client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules=['indexUID']) token_client = meilisearch.Client(BASE_URL, token) response = token_client.index('indexUID').search('') From 19c90cac2e802004a93fb1d4a84bfe7dbc0dc891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:21 +0200 Subject: [PATCH 05/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index 5643d58e..1e08ce33 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -40,7 +40,7 @@ def test_generate_tenant_token_with_search_rules_on_one_index(get_private_key, e def test_generate_tenant_token_with_api_key(client, get_private_key, empty_index): """Tests create a tenant token with search rules and an api key.""" empty_index() - token = client.generate_tenant_token(uid=get_private_key['uid'], search_rules=["*"], api_key=get_private_key['key']) + token = client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules=["*"], api_key=get_private_key['key']) token_client = meilisearch.Client(BASE_URL, token) response = token_client.index('indexUID').search('') From 28faa65cbd0ad0c8753de56863abc8cf797404e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:26 +0200 Subject: [PATCH 06/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index 1e08ce33..f3208f5d 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -53,7 +53,7 @@ def test_generate_tenant_token_with_expires_at(client, get_private_key, empty_in client = meilisearch.Client(BASE_URL, get_private_key['key']) tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1) - token = client.generate_tenant_token(uid=get_private_key['uid'], search_rules=["*"], expires_at=tomorrow) + token = client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules=["*"], expires_at=tomorrow) token_client = meilisearch.Client(BASE_URL, token) response = token_client.index('indexUID').search('') From 7e8b4b7327fe3eab309cdf33ecacd02078b668cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:31 +0200 Subject: [PATCH 07/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index f3208f5d..3e3d9cca 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -65,7 +65,7 @@ def test_generate_tenant_token_with_empty_search_rules_in_list(get_private_key): client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(uid=get_private_key['uid'], search_rules=['']) + client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules=['']) def test_generate_tenant_token_without_search_rules_in_list(get_private_key): """Tests create a tenant token without search rules.""" From 36b90b7d18e110ab6355cb1814626c4c2d69a0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:36 +0200 Subject: [PATCH 08/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index 3e3d9cca..b15ef9ed 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -72,7 +72,7 @@ def test_generate_tenant_token_without_search_rules_in_list(get_private_key): client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(uid=get_private_key['uid'], search_rules=[]) + client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules=[]) def test_generate_tenant_token_without_search_rules_in_dict(get_private_key): """Tests create a tenant token without search rules.""" From 744dac73028dacb2e91f6c999420f82411f34233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:41 +0200 Subject: [PATCH 09/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index b15ef9ed..3e9535c3 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -79,7 +79,7 @@ def test_generate_tenant_token_without_search_rules_in_dict(get_private_key): client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(uid=get_private_key['uid'], search_rules={}) + client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules={}) def test_generate_tenant_token_with_empty_search_rules_in_dict(get_private_key): """Tests create a tenant token without search rules.""" From 3866553b7e299cbfb3054897a716ea6c97b33c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:46 +0200 Subject: [PATCH 10/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index 3e9535c3..3d82bc45 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -86,7 +86,7 @@ def test_generate_tenant_token_with_empty_search_rules_in_dict(get_private_key): client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(uid=get_private_key['uid'], search_rules={''}) + client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules={''}) def test_generate_tenant_token_with_bad_expires_at(client, get_private_key): """Tests create a tenant token with a bad expires at.""" From 3b04b766a4940024295e700738b17f97a54eabe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:51 +0200 Subject: [PATCH 11/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index 3d82bc45..04c5f76a 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -95,7 +95,7 @@ def test_generate_tenant_token_with_bad_expires_at(client, get_private_key): yesterday = datetime.datetime.utcnow() + datetime.timedelta(days=-1) with pytest.raises(Exception): - client.generate_tenant_token(uid=get_private_key['uid'], search_rules=["*"], expires_at=yesterday) + client.generate_tenant_token(api_key_uid=get_private_key['uid'], search_rules=["*"], expires_at=yesterday) def test_generate_tenant_token_with_no_api_key(client): """Tests create a tenant token with no api key.""" From 20d31066ba5202ee80f6afe7c9433e5e1c66739e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie?= Date: Mon, 27 Jun 2022 12:03:56 +0200 Subject: [PATCH 12/12] Update tests/client/test_client_tenant_token.py Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> --- tests/client/test_client_tenant_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index 04c5f76a..cc290dbd 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -109,4 +109,4 @@ def test_generate_tenant_token_with_no_uid(client, get_private_key): client = meilisearch.Client(BASE_URL, get_private_key['key']) with pytest.raises(Exception): - client.generate_tenant_token(uid=None, search_rules=["*"]) + client.generate_tenant_token(api_key_uid=None, search_rules=["*"])