Skip to content

Commit b4e4708

Browse files
Dina SamatovaDina Samatova
authored andcommitted
Refactor & Test: Enhance JWT expiration handling, resolve algorithm naming conflict, and add Twilio Video Room test
- Improved JWT expiration logic: - Replaced time.time() with datetime.datetime.utcnow() to ensure more accurate expiration handling. - Applied datetime.timedelta(seconds=...) for better timestamp calculations. - Ensured compatibility with jwt.encode() by converting expiration times using .timestamp(). - Resolved naming issue between ALGORITHM and algorithm: - Renamed the algorithm parameter to jwt_algorithm to avoid conflicts with the ALGORITHM constant. - Updated all references to maintain consistency throughout the class. - Added unit test for Twilio Video Room creation: - Integrated unittest framework for structured testing. - Used responses library to mock Twilio API calls. - Implemented a test case that validates room creation by checking sid, unique_name, and status. These updates improve JWT handling, fix potential naming conflicts, and introduce automated testing for Twilio API interactions.
1 parent 71fb731 commit b4e4708

File tree

2 files changed

+52
-18
lines changed

2 files changed

+52
-18
lines changed

tests/unit/rest/test__video_rooms.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import unittest
2+
import responses
3+
from twilio.rest import Client
4+
5+
6+
class TestVideoRooms(unittest.TestCase):
7+
@responses.activate
8+
def test_create_video_room(self):
9+
# Configuración de credenciales de prueba
10+
account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
11+
auth_token = "your_auth_token"
12+
client = Client(account_sid, auth_token)
13+
14+
# Simulación de la respuesta del endpoint de creación de salas de video
15+
responses.add(
16+
responses.POST,
17+
"https://video.twilio.com/v1/Rooms",
18+
json={
19+
"sid": "RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
20+
"unique_name": "TestRoom",
21+
"status": "in-progress",
22+
},
23+
status=201,
24+
content_type="application/json",
25+
)
26+
27+
# Llamada al método para crear la sala
28+
room = client.video.rooms.create(unique_name="TestRoom", type="group")
29+
30+
# Verificaciones de la respuesta
31+
self.assertEqual(room.sid, "RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
32+
self.assertEqual(room.unique_name, "TestRoom")
33+
self.assertEqual(room.status, "in-progress")
34+
35+
36+
if __name__ == "__main__":
37+
unittest.main()

twilio/jwt/__init__.py

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import jwt as jwt_lib
2-
import time
2+
import datetime
33

44

55
__all__ = ["Jwt", "JwtDecodeError"]
@@ -20,25 +20,18 @@ def __init__(
2020
secret_key,
2121
issuer,
2222
subject=None,
23-
algorithm=None,
23+
jwt_algorithm=None,
2424
nbf=GENERATE,
2525
ttl=3600,
2626
valid_until=None,
2727
):
2828
self.secret_key = secret_key
29-
""":type str: The secret used to encode the JWT"""
3029
self.issuer = issuer
31-
""":type str: The issuer of this JWT"""
3230
self.subject = subject
33-
""":type str: The subject of this JWT, omitted from payload by default"""
34-
self.algorithm = algorithm or self.ALGORITHM
35-
""":type str: The algorithm used to encode the JWT, defaults to 'HS256'"""
31+
self.jwt_algorithm = jwt_algorithm or self.ALGORITHM
3632
self.nbf = nbf
37-
""":type int: Time in secs since epoch before which this JWT is invalid. Defaults to now."""
3833
self.ttl = ttl
39-
""":type int: Time to live of the JWT in seconds, defaults to 1 hour"""
4034
self.valid_until = valid_until
41-
""":type int: Time in secs since epoch this JWT is valid for. Overrides ttl if provided."""
4235

4336
self.__decoded_payload = None
4437
self.__decoded_headers = None
@@ -55,14 +48,14 @@ def _generate_headers(self):
5548
def _from_jwt(cls, headers, payload, key=None):
5649
"""
5750
Class specific implementation of from_jwt which should take jwt components and return
58-
and instance of this Class with jwt information loaded.
59-
:return: Jwt object containing the headers, payload and key
51+
an instance of this Class with jwt information loaded.
52+
:return: Jwt object containing the headers, payload, and key
6053
"""
6154
jwt = Jwt(
6255
secret_key=key,
6356
issuer=payload.get("iss", None),
6457
subject=payload.get("sub", None),
65-
algorithm=headers.get("alg", None),
58+
jwt_algorithm=headers.get("alg", None),
6659
valid_until=payload.get("exp", None),
6760
nbf=payload.get("nbf", None),
6861
)
@@ -77,10 +70,12 @@ def payload(self):
7770

7871
payload = self._generate_payload().copy()
7972
payload["iss"] = self.issuer
80-
payload["exp"] = int(time.time()) + self.ttl
73+
payload["exp"] = (
74+
datetime.datetime.utcnow() + datetime.timedelta(seconds=self.ttl)
75+
).timestamp()
8176
if self.nbf is not None:
8277
if self.nbf == self.GENERATE:
83-
payload["nbf"] = int(time.time())
78+
payload["nbf"] = datetime.datetime.utcnow().timestamp()
8479
else:
8580
payload["nbf"] = self.nbf
8681
if self.valid_until:
@@ -97,7 +92,7 @@ def headers(self):
9792

9893
headers = self._generate_headers().copy()
9994
headers["typ"] = "JWT"
100-
headers["alg"] = self.algorithm
95+
headers["alg"] = self.jwt_algorithm
10196
return headers
10297

10398
def to_jwt(self, ttl=None):
@@ -114,10 +109,12 @@ def to_jwt(self, ttl=None):
114109

115110
payload = self.payload.copy()
116111
if ttl:
117-
payload["exp"] = int(time.time()) + ttl
112+
payload["exp"] = (
113+
datetime.datetime.utcnow() + datetime.timedelta(seconds=ttl)
114+
).timestamp()
118115

119116
return jwt_lib.encode(
120-
payload, self.secret_key, algorithm=self.algorithm, headers=headers
117+
payload, self.secret_key, algorithm=self.jwt_algorithm, headers=headers
121118
)
122119

123120
@classmethod

0 commit comments

Comments
 (0)