|
1 | 1 | from typing import Any, Dict, List, Optional
|
2 | 2 |
|
| 3 | +import base64 |
| 4 | +import hashlib |
| 5 | +import hmac |
| 6 | +import json |
3 | 7 | from meilisearch.index import Index
|
4 | 8 | from meilisearch.config import Config
|
5 | 9 | from meilisearch.task import get_task, get_tasks, wait_for_task
|
6 | 10 | from meilisearch._httprequests import HttpRequests
|
7 | 11 | from meilisearch.errors import MeiliSearchError
|
8 |
| -import base64 |
9 |
| -import hashlib |
10 |
| -import hmac |
11 |
| -import json |
12 | 12 |
|
13 | 13 | class Client():
|
14 | 14 | """
|
@@ -469,33 +469,56 @@ def wait_for_task(
|
469 | 469 | """
|
470 | 470 | return wait_for_task(self.config, uid, timeout_in_ms, interval_in_ms)
|
471 | 471 |
|
472 |
| - def base64url_encode( |
473 |
| - self, |
474 |
| - input: bytes |
475 |
| - ) -> str: |
476 |
| - return base64.urlsafe_b64encode(input).decode('utf-8').replace('=','') |
477 |
| - |
478 | 472 | def generate_tenant_token(
|
479 | 473 | self,
|
480 |
| - parentApiKey: str, |
481 |
| - payload: str |
| 474 | + options: str, |
| 475 | + api_key: Optional[str] = None |
482 | 476 | ) -> str:
|
| 477 | + """Generate a JWT token for the use of multitenancy. |
| 478 | +
|
| 479 | + Parameters |
| 480 | + ---------- |
| 481 | + options: |
| 482 | + Options, the information to generate the token (ex: { 'searchRules': ['*'], 'exp': '1645089029' }). |
| 483 | + `searchRules`: A Dictionary which contains the rules to be enforced at search time for all or specific |
| 484 | + accessible indexes for the signing API Key. |
| 485 | + In the specific case of you want to have any restrictions you can also use a array ["*"]. |
| 486 | + Note that if an exp value is included it should a `timestamp`. |
483 | 487 |
|
| 488 | + Returns |
| 489 | + ------- |
| 490 | + jwt_token: |
| 491 | + A string containing the jwt tenant token. |
| 492 | +
|
| 493 | + Raises |
| 494 | + ------ |
| 495 | + MeiliSearchApiError |
| 496 | + An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://docs.meilisearch.com/errors/#meilisearch-errors |
| 497 | + """ |
484 | 498 | header = {
|
485 | 499 | "typ": "JWT",
|
486 | 500 | "alg": "HS256"
|
487 | 501 | }
|
488 | 502 |
|
489 |
| - payload['apiKeyPrefix'] = parentApiKey[0:8] |
| 503 | + if api_key is None: |
| 504 | + api_key = self.config.api_key |
| 505 | + |
| 506 | + options['apiKeyPrefix'] = api_key[0:8] |
490 | 507 |
|
491 | 508 | json_header = json.dumps(header, separators=(",",":")).encode()
|
492 |
| - json_payload = json.dumps(payload, separators=(",",":")).encode() |
| 509 | + json_options = json.dumps(options, separators=(",",":")).encode() |
493 | 510 |
|
494 |
| - header_encode = self.base64url_encode(json_header) |
495 |
| - header_payload = self.base64url_encode(json_payload) |
| 511 | + header_encode = self._base64url_encode(json_header) |
| 512 | + header_options = self._base64url_encode(json_options) |
496 | 513 |
|
497 |
| - secret_encoded = parentApiKey.encode() |
498 |
| - signature = hmac.new(secret_encoded, (header_encode + "." + header_payload).encode(), hashlib.sha256).digest() |
499 |
| - jwt_token = header_encode + '.' + header_payload + '.' + self.base64url_encode(signature) |
| 514 | + secret_encoded = api_key.encode() |
| 515 | + signature = hmac.new(secret_encoded, (header_encode + "." + header_options).encode(), hashlib.sha256).digest() |
| 516 | + jwt_token = header_encode + '.' + header_options + '.' + self._base64url_encode(signature) |
500 | 517 |
|
501 | 518 | return jwt_token
|
| 519 | + |
| 520 | + @staticmethod |
| 521 | + def _base64url_encode( |
| 522 | + data: bytes |
| 523 | + ) -> str: |
| 524 | + return base64.urlsafe_b64encode(data).decode('utf-8').replace('=','') |
0 commit comments