Skip to content

test: added test for Video Room, fix: resolved conflict of duplicated names, enhanced code of 'time' logic #845

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions tests/unit/rest/test__video_rooms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import unittest
import responses
from twilio.rest import Client


class TestVideoRooms(unittest.TestCase):
@responses.activate
def test_create_video_room(self):
# Configuración de credenciales de prueba
account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
auth_token = "your_auth_token"
client = Client(account_sid, auth_token)

# Simulación de la respuesta del endpoint de creación de salas de video
responses.add(
responses.POST,
"https://video.twilio.com/v1/Rooms",
json={
"sid": "RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"unique_name": "TestRoom",
"status": "in-progress",
},
status=201,
content_type="application/json",
)

# Llamada al método para crear la sala
room = client.video.rooms.create(unique_name="TestRoom", type="group")

# Verificaciones de la respuesta
self.assertEqual(room.sid, "RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
self.assertEqual(room.unique_name, "TestRoom")
self.assertEqual(room.status, "in-progress")


if __name__ == "__main__":
unittest.main()
50 changes: 30 additions & 20 deletions twilio/jwt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import jwt as jwt_lib
import time
import datetime


__all__ = ["Jwt", "JwtDecodeError"]
Expand All @@ -20,25 +20,18 @@ def __init__(
secret_key,
issuer,
subject=None,
algorithm=None,
jwt_algorithm=None, # Renamed from `algorithm` to `jwt_algorithm` for clarity
nbf=GENERATE,
ttl=3600,
valid_until=None,
):
self.secret_key = secret_key
""":type str: The secret used to encode the JWT"""
self.issuer = issuer
""":type str: The issuer of this JWT"""
self.subject = subject
""":type str: The subject of this JWT, omitted from payload by default"""
self.algorithm = algorithm or self.ALGORITHM
""":type str: The algorithm used to encode the JWT, defaults to 'HS256'"""
self.jwt_algorithm = jwt_algorithm or self.ALGORITHM # Updated variable name
self.nbf = nbf
""":type int: Time in secs since epoch before which this JWT is invalid. Defaults to now."""
self.ttl = ttl
""":type int: Time to live of the JWT in seconds, defaults to 1 hour"""
self.valid_until = valid_until
""":type int: Time in secs since epoch this JWT is valid for. Overrides ttl if provided."""

self.__decoded_payload = None
self.__decoded_headers = None
Expand All @@ -55,14 +48,14 @@ def _generate_headers(self):
def _from_jwt(cls, headers, payload, key=None):
"""
Class specific implementation of from_jwt which should take jwt components and return
and instance of this Class with jwt information loaded.
:return: Jwt object containing the headers, payload and key
an instance of this Class with jwt information loaded.
:return: Jwt object containing the headers, payload, and key
"""
jwt = Jwt(
secret_key=key,
issuer=payload.get("iss", None),
subject=payload.get("sub", None),
algorithm=headers.get("alg", None),
jwt_algorithm=headers.get("alg", None), # Updated variable name
valid_until=payload.get("exp", None),
nbf=payload.get("nbf", None),
)
Expand All @@ -77,12 +70,24 @@ def payload(self):

payload = self._generate_payload().copy()
payload["iss"] = self.issuer
payload["exp"] = int(time.time()) + self.ttl

# Changed from `int(time.time()) + self.ttl` to `datetime.now(timezone.utc) + timedelta(seconds=self.ttl)`
# This ensures that the timestamp is timezone-aware and prevents potential issues with time handling.
payload["exp"] = (
datetime.datetime.now(datetime.timezone.utc)
+ datetime.timedelta(seconds=self.ttl)
).timestamp()

if self.nbf is not None:
if self.nbf == self.GENERATE:
payload["nbf"] = int(time.time())
# Replaced `int(time.time())` with `datetime.now(timezone.utc).timestamp()`
# This ensures the `nbf` value is also timezone-aware.
payload["nbf"] = datetime.datetime.now(
datetime.timezone.utc
).timestamp()
else:
payload["nbf"] = self.nbf

if self.valid_until:
payload["exp"] = self.valid_until
if self.subject:
Expand All @@ -97,7 +102,7 @@ def headers(self):

headers = self._generate_headers().copy()
headers["typ"] = "JWT"
headers["alg"] = self.algorithm
headers["alg"] = self.jwt_algorithm # Updated variable name
return headers

def to_jwt(self, ttl=None):
Expand All @@ -111,13 +116,18 @@ def to_jwt(self, ttl=None):
raise ValueError("JWT does not have a signing key configured.")

headers = self.headers.copy()

payload = self.payload.copy()

if ttl:
payload["exp"] = int(time.time()) + ttl
# Replaced `int(time.time()) + ttl` with `datetime.now(timezone.utc) + timedelta(seconds=ttl)`
# Ensures consistency across all timestamp calculations.
payload["exp"] = (
datetime.datetime.now(datetime.timezone.utc)
+ datetime.timedelta(seconds=ttl)
).timestamp()

return jwt_lib.encode(
payload, self.secret_key, algorithm=self.algorithm, headers=headers
payload, self.secret_key, algorithm=self.jwt_algorithm, headers=headers
)

@classmethod
Expand Down Expand Up @@ -147,7 +157,7 @@ def from_jwt(cls, jwt, key=""):
key,
algorithms=[cls.ALGORITHM],
options={
"verify_signature": verify,
"verify_signature": verify, # Ensured signature verification if a key is provided
"verify_exp": True,
"verify_nbf": True,
},
Expand Down