From 72401b229fabcd7ca5f6c7309d77f3c30c9376c7 Mon Sep 17 00:00:00 2001 From: Mateusz Mandera Date: Mon, 16 Dec 2019 06:27:34 +0100 Subject: [PATCH] utils: Add a function to check if string can be an API key. --- zerver/lib/utils.py | 4 ++++ zerver/tests/test_decorators.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/zerver/lib/utils.py b/zerver/lib/utils.py index 8eba3809be..e918e41975 100644 --- a/zerver/lib/utils.py +++ b/zerver/lib/utils.py @@ -6,6 +6,7 @@ import hashlib import heapq import itertools import os +import re import string from time import sleep from itertools import zip_longest @@ -117,6 +118,9 @@ def generate_api_key() -> str: api_key = base64.b64encode(os.urandom(24), altchars=altchars).decode("utf-8") return api_key +def has_api_key_format(key: str) -> bool: + return bool(re.fullmatch(r"([A-Za-z0-9]){32}", key)) + def query_chunker(queries: List[Any], id_collector: Optional[Set[int]]=None, chunk_size: int=1000, diff --git a/zerver/tests/test_decorators.py b/zerver/tests/test_decorators.py index 6b7e6a3de7..e71746dd50 100644 --- a/zerver/tests/test_decorators.py +++ b/zerver/tests/test_decorators.py @@ -25,6 +25,7 @@ from zerver.lib.test_classes import ( from zerver.lib.response import json_response, json_success from zerver.lib.users import get_api_key from zerver.lib.user_agent import parse_user_agent +from zerver.lib.utils import generate_api_key, has_api_key_format from zerver.lib.request import \ REQ, has_request_variables, RequestVariableMissingError, \ RequestVariableConversionError, RequestConfusingParmsError @@ -1292,6 +1293,17 @@ class TestValidateApiKey(ZulipTestCase): self.webhook_bot = get_user('webhook-bot@zulip.com', zulip_realm) self.default_bot = get_user('default-bot@zulip.com', zulip_realm) + def test_has_api_key_format(self) -> None: + self.assertFalse(has_api_key_format("TooShort")) + # Has an invalid character: + self.assertFalse(has_api_key_format("32LONGXXXXXXXXXXXXXXXXXXXXXXXXX-")) + # Too long: + self.assertFalse(has_api_key_format("33LONGXXXXXXXXXXXXXXXXXXXXXXXXXXX")) + + self.assertTrue(has_api_key_format("VIzRVw2CspUOnEm9Yu5vQiQtJNkvETkp")) + for i in range(0, 10): + self.assertTrue(has_api_key_format(generate_api_key())) + def test_validate_api_key_if_profile_does_not_exist(self) -> None: with self.assertRaises(JsonableError): validate_api_key(HostRequestMock(), 'email@doesnotexist.com', 'api_key')