From 420b2540ca354c1cd2cb80f2a6d69fb5b21e5604 Mon Sep 17 00:00:00 2001 From: Karol Konkol Date: Thu, 10 Sep 2026 16:26:55 +0200 Subject: [PATCH 1/2] Add ttl to create_moq_access Regenerated MoqAccessConfig from fishjam openapi.yaml (fce-3832/moq-token-ttl). Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_013EKXgj4SvESh4S99791s1N --- .../models/moq_access_config.py | 21 +++++++++++++++++++ fishjam/api/_fishjam_client.py | 7 ++++++- tests/test_room_api.py | 14 +++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/fishjam/_fishjam_openapi_client/models/moq_access_config.py b/fishjam/_fishjam_openapi_client/models/moq_access_config.py index ee64e4e..29c154a 100644 --- a/fishjam/_fishjam_openapi_client/models/moq_access_config.py +++ b/fishjam/_fishjam_openapi_client/models/moq_access_config.py @@ -18,10 +18,13 @@ class MoqAccessConfig: publish_path (None | str | Unset): Path under the root the token grants publish access to Example: my-stream. subscribe_path (None | str | Unset): Path under the root the token grants subscribe access to Example: my- stream. + ttl (int | None | Unset): Token time to live in seconds. Defaults to 3600 (1 hour), maximum is 86400 (24 hours). + Example: 3600. """ publish_path: None | str | Unset = UNSET subscribe_path: None | str | Unset = UNSET + ttl: int | None | Unset = UNSET def to_dict(self) -> dict[str, Any]: publish_path: None | str | Unset @@ -36,6 +39,12 @@ def to_dict(self) -> dict[str, Any]: else: subscribe_path = self.subscribe_path + ttl: int | None | Unset + if isinstance(self.ttl, Unset): + ttl = UNSET + else: + ttl = self.ttl + field_dict: dict[str, Any] = {} field_dict.update({}) @@ -43,6 +52,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["publishPath"] = publish_path if subscribe_path is not UNSET: field_dict["subscribePath"] = subscribe_path + if ttl is not UNSET: + field_dict["ttl"] = ttl return field_dict @@ -68,9 +79,19 @@ def _parse_subscribe_path(data: object) -> None | str | Unset: subscribe_path = _parse_subscribe_path(d.pop("subscribePath", UNSET)) + def _parse_ttl(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + ttl = _parse_ttl(d.pop("ttl", UNSET)) + moq_access_config = cls( publish_path=publish_path, subscribe_path=subscribe_path, + ttl=ttl, ) return moq_access_config diff --git a/fishjam/api/_fishjam_client.py b/fishjam/api/_fishjam_client.py index 44ce2db..ffb82fd 100644 --- a/fishjam/api/_fishjam_client.py +++ b/fishjam/api/_fishjam_client.py @@ -514,12 +514,15 @@ def create_moq_access( self, publish_path: str | None = None, subscribe_path: str | None = None, + ttl: int | None = None, ) -> MoqAccess: """Generates MoQ relay connection details. Args: publish_path: Path the access grants publish access to. subscribe_path: Path the access grants subscribe access to. + ttl: Token time to live in seconds. Defaults to 3600 (1 hour), + maximum is 86400 (24 hours). Returns: MoqAccess: The relay connection details, containing the @@ -527,7 +530,9 @@ def create_moq_access( parameter) and the ``token`` itself. """ config = MoqAccessConfig( - publish_path=publish_path, subscribe_path=subscribe_path + publish_path=publish_path, + subscribe_path=subscribe_path, + ttl=ttl if ttl is not None else UNSET, ) response = cast( MoqAccess, diff --git a/tests/test_room_api.py b/tests/test_room_api.py index 1287cf8..b361431 100644 --- a/tests/test_room_api.py +++ b/tests/test_room_api.py @@ -1,3 +1,5 @@ +import base64 +import json from unittest.mock import Mock, patch import httpx @@ -342,6 +344,18 @@ def test_valid_both(self, room_api: FishjamClient): assert isinstance(access.connection_url, str) assert isinstance(access.token, str) + def test_ttl_sets_token_expiry(self, room_api: FishjamClient): + access = room_api.create_moq_access(publish_path="test-stream", ttl=120) + + _header, payload, _signature = access.token.split(".") + payload += "=" * (-len(payload) % 4) + claims = json.loads(base64.urlsafe_b64decode(payload)) + assert claims["exp"] - claims["iat"] == 120 + + def test_invalid_ttl(self, room_api: FishjamClient): + with pytest.raises(BadRequestError): + room_api.create_moq_access(publish_path="test-stream", ttl=0) + def test_unauthorized(self): room_api = FishjamClient(FISHJAM_ID, "invalid") From bca2800500769ff5751a984a9664b107185761e6 Mon Sep 17 00:00:00 2001 From: Karol Konkol Date: Fri, 11 Sep 2026 11:13:23 +0200 Subject: [PATCH 2/2] Raise MoQ token ttl maximum to 7 days Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01GZ2sxpkxEiCEjoHpXgQNEF --- fishjam/_fishjam_openapi_client/models/moq_access_config.py | 2 +- fishjam/api/_fishjam_client.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fishjam/_fishjam_openapi_client/models/moq_access_config.py b/fishjam/_fishjam_openapi_client/models/moq_access_config.py index 29c154a..35ee25c 100644 --- a/fishjam/_fishjam_openapi_client/models/moq_access_config.py +++ b/fishjam/_fishjam_openapi_client/models/moq_access_config.py @@ -18,7 +18,7 @@ class MoqAccessConfig: publish_path (None | str | Unset): Path under the root the token grants publish access to Example: my-stream. subscribe_path (None | str | Unset): Path under the root the token grants subscribe access to Example: my- stream. - ttl (int | None | Unset): Token time to live in seconds. Defaults to 3600 (1 hour), maximum is 86400 (24 hours). + ttl (int | None | Unset): Token time to live in seconds. Defaults to 3600 (1 hour), maximum is 604800 (7 days). Example: 3600. """ diff --git a/fishjam/api/_fishjam_client.py b/fishjam/api/_fishjam_client.py index ffb82fd..fc4e91e 100644 --- a/fishjam/api/_fishjam_client.py +++ b/fishjam/api/_fishjam_client.py @@ -522,7 +522,7 @@ def create_moq_access( publish_path: Path the access grants publish access to. subscribe_path: Path the access grants subscribe access to. ttl: Token time to live in seconds. Defaults to 3600 (1 hour), - maximum is 86400 (24 hours). + maximum is 604800 (7 days). Returns: MoqAccess: The relay connection details, containing the