diff --git a/cloudinary/auth_token.py b/cloudinary/auth_token.py index 8ddeacd..417c990 100644 --- a/cloudinary/auth_token.py +++ b/cloudinary/auth_token.py @@ -12,6 +12,9 @@ def generate(url=None, acl=None, start_time=None, duration=None, expiration=None, ip=None, key=None, token_name=AUTH_TOKEN_NAME, **_): + start_time = _ensure_int(start_time) + duration = _ensure_int(duration) + expiration = _ensure_int(expiration) if expiration is None: if duration is not None: @@ -52,3 +55,22 @@ def _escape_to_lower(url): escaped_url = smart_escape(url, unsafe=AUTH_TOKEN_UNSAFE_RE) escaped_url = re.sub(r"%[0-9A-F]{2}", lambda x: x.group(0).lower(), escaped_url) return escaped_url + +def _ensure_int(value): + """ + Ensures the input value is an integer. + Attempts to cast it to an integer if it is not already. + + :param value: The value to ensure as an integer. + :type value: Any + :return: The integer value. + :rtype: int + :raises ValueError: If the value cannot be converted to an integer. + """ + if isinstance(value, int) or not value: + return value + + try: + return int(value) + except (ValueError, TypeError): + raise ValueError("Value '" + value + "' must be an integer.") diff --git a/test/test_auth_token.py b/test/test_auth_token.py index 9160731..349365f 100644 --- a/test/test_auth_token.py +++ b/test/test_auth_token.py @@ -11,9 +11,11 @@ class AuthTokenTest(unittest.TestCase): def setUp(self): self.url_backup = os.environ.get("CLOUDINARY_URL") - os.environ["CLOUDINARY_URL"] = "cloudinary://a:b@test123" + os.environ["CLOUDINARY_URL"] = ("cloudinary://a:b@test123?" + "auth_token[duration]=300" + "&auth_token[start_time]=11111111" + "&auth_token[key]=" + KEY) cloudinary.reset_config() - cloudinary.config(auth_token={"key": KEY, "duration": 300, "start_time": 11111111}) def tearDown(self): with ignore_exception(): @@ -93,6 +95,16 @@ def test_generate_token_string(self): "8e39600cc18cec339b21fe2b05fcb64b98de373355f8ce732c35710d8b10259f" ) + def test_generate_token_string_from_string_values(self): + user = "foobar" + token_options = {"key": KEY, "duration": "300", "acl": "/*/t_%s" % user, "start_time": "222222222"} + cookie_token = cloudinary.utils.generate_auth_token(**token_options) + self.assertEqual( + cookie_token, + "__cld_token__=st=222222222~exp=222222522~acl=%2f*%2ft_foobar~hmac=" + "8e39600cc18cec339b21fe2b05fcb64b98de373355f8ce732c35710d8b10259f" + ) + def test_should_ignore_url_if_acl_is_provided(self): token_options = {"key": KEY, "duration": 300, "acl": '/image/*', "start_time": 222222222} acl_token = cloudinary.utils.generate_auth_token(**token_options)