From f625df65083f0d5757fc342cd07d416d11414298 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Mon, 23 Feb 2026 16:42:46 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(backend)=20refactor=20extern?= =?UTF-8?q?al=20API=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor tests to avoid duplicating JWT secret key configuration. Introduce configuration of the JWT audience, which previously had no default value. --- .../core/tests/test_external_api_rooms.py | 76 +++++-------------- .../core/tests/test_external_api_token.py | 7 +- src/backend/meet/settings.py | 3 + 3 files changed, 23 insertions(+), 63 deletions(-) diff --git a/src/backend/core/tests/test_external_api_rooms.py b/src/backend/core/tests/test_external_api_rooms.py index 7a6ae487..c4d7322a 100644 --- a/src/backend/core/tests/test_external_api_rooms.py +++ b/src/backend/core/tests/test_external_api_rooms.py @@ -55,9 +55,8 @@ def test_api_rooms_list_requires_authentication(): assert response.status_code == 401 -def test_api_rooms_list_inactive_user(settings): +def test_api_rooms_list_inactive_user(): """List should return 401 if user is inactive.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user1 = UserFactory(is_active=False) RoomFactory(users=[(user1, RoleChoices.OWNER)]) @@ -72,11 +71,9 @@ def test_api_rooms_list_inactive_user(settings): assert "user account is disabled" in str(response.data).lower() -def test_api_rooms_list_with_valid_token(settings): +def test_api_rooms_list_with_valid_token(): """Listing rooms with valid token should succeed.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" - user = UserFactory() room = RoomFactory(users=[(user, RoleChoices.OWNER)]) @@ -92,9 +89,8 @@ def test_api_rooms_list_with_valid_token(settings): assert response.data["results"][0]["id"] == str(room.id) -def test_api_rooms_list_with_no_rooms(settings): +def test_api_rooms_list_with_no_rooms(): """Listing rooms with a valid token returns an empty list when there are no rooms.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() @@ -112,7 +108,6 @@ def test_api_rooms_list_with_no_rooms(settings): def test_api_rooms_list_with_expired_token(settings): """Listing rooms with expired token should return 401.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" settings.APPLICATION_JWT_EXPIRATION_SECONDS = 0 user = UserFactory() @@ -153,9 +148,8 @@ def test_api_rooms_list_with_invalid_rs_token(settings): assert response.status_code == 400 -def test_api_rooms_list_missing_scope(settings): +def test_api_rooms_list_missing_scope(): """Listing rooms without required scope should return 403.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() @@ -173,9 +167,8 @@ def test_api_rooms_list_missing_scope(settings): ) -def test_api_rooms_list_no_scope(settings): +def test_api_rooms_list_no_scope(): """Listing rooms without any scope should return 403.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() @@ -190,9 +183,8 @@ def test_api_rooms_list_no_scope(settings): assert "insufficient permissions." in str(response.data).lower() -def test_api_rooms_list_filters_by_user(settings): +def test_api_rooms_list_filters_by_user(): """List should only return rooms accessible to the authenticated user.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user1 = UserFactory() user2 = UserFactory() @@ -217,11 +209,9 @@ def test_api_rooms_list_filters_by_user(settings): assert str(room2.id) not in returned_ids -def test_api_rooms_retrieve_requires_authentication(settings): +def test_api_rooms_retrieve_requires_authentication(): """Retrieving rooms without authentication should return 401.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" - user1 = UserFactory() room1 = RoomFactory(users=[(user1, RoleChoices.OWNER)]) @@ -231,9 +221,8 @@ def test_api_rooms_retrieve_requires_authentication(settings): assert response.status_code == 401 -def test_api_rooms_retrieve_inactive_user(settings): +def test_api_rooms_retrieve_inactive_user(): """Retrieve should return 401 if user is inactive.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user1 = UserFactory(is_active=False) room1 = RoomFactory(users=[(user1, RoleChoices.OWNER)]) @@ -250,7 +239,6 @@ def test_api_rooms_retrieve_inactive_user(settings): def test_api_rooms_retrieve_with_expired_token(settings): """Retrieving rooms with expired token should return 401.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" settings.APPLICATION_JWT_EXPIRATION_SECONDS = 0 user = UserFactory() @@ -295,9 +283,8 @@ def test_api_rooms_retrieve_with_invalid_rs_token(settings): assert response.status_code == 400 -def test_api_rooms_retrieve_requires_scope(settings): +def test_api_rooms_retrieve_requires_scope(): """Retrieving a room requires ROOMS_RETRIEVE scope.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() room = RoomFactory(users=[(user, RoleChoices.OWNER)]) @@ -315,9 +302,8 @@ def test_api_rooms_retrieve_requires_scope(settings): ) -def test_api_rooms_retrieve_no_scope(settings): +def test_api_rooms_retrieve_no_scope(): """Retrieving rooms without any scope should return 403.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() @@ -335,7 +321,6 @@ def test_api_rooms_retrieve_no_scope(settings): def test_api_rooms_retrieve_success(settings): """Retrieving a room with correct scope should succeed.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" settings.APPLICATION_BASE_URL = "http://your-application.com" settings.ROOM_TELEPHONY_ENABLED = True settings.ROOM_TELEPHONY_PHONE_NUMBER = "+1-555-0100" @@ -367,9 +352,8 @@ def test_api_rooms_retrieve_success(settings): } -def test_api_rooms_retrieve_success_by_user(settings): +def test_api_rooms_retrieve_success_by_user(): """Retrieve should only return rooms accessible to the authenticated user.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user1 = UserFactory() user2 = UserFactory() @@ -408,9 +392,8 @@ def test_api_rooms_retrieve_success_by_user(settings): assert response.status_code == 200 -def test_api_rooms_retrieve_not_found(settings): +def test_api_rooms_retrieve_not_found(): """Retrieving a non-existing room with correct scope should return a 404.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() token = generate_test_token(user, [ApplicationScope.ROOMS_RETRIEVE]) @@ -423,11 +406,9 @@ def test_api_rooms_retrieve_not_found(settings): assert "no room matches the given query." in str(response.data).lower() -def test_api_rooms_create_requires_authentication(settings): +def test_api_rooms_create_requires_authentication(): """Creating rooms without authentication should return 401.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" - client = APIClient() response = client.post("/external-api/v1.0/rooms/") @@ -436,7 +417,6 @@ def test_api_rooms_create_requires_authentication(settings): def test_api_rooms_create_with_expired_token(settings): """Creating rooms with expired token should return 401.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" settings.APPLICATION_JWT_EXPIRATION_SECONDS = 0 user = UserFactory() @@ -477,9 +457,8 @@ def test_api_rooms_create_with_invalid_rs_token(settings): assert response.status_code == 400 -def test_api_rooms_create_inactive_user(settings): +def test_api_rooms_create_inactive_user(): """Create should return 401 if user is inactive.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user1 = UserFactory(is_active=False) @@ -493,9 +472,8 @@ def test_api_rooms_create_inactive_user(settings): assert "user account is disabled" in str(response.data).lower() -def test_api_rooms_create_requires_scope(settings): +def test_api_rooms_create_requires_scope(): """Creating a room requires ROOMS_CREATE scope.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() # Token without ROOMS_CREATE scope @@ -512,9 +490,8 @@ def test_api_rooms_create_requires_scope(settings): ) -def test_api_rooms_create_no_scope(settings): +def test_api_rooms_create_no_scope(): """Creating rooms without any scope should return 403.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() @@ -529,9 +506,8 @@ def test_api_rooms_create_no_scope(settings): assert "insufficient permissions." in str(response.data).lower() -def test_api_rooms_create_success(settings): +def test_api_rooms_create_success(): """Creating a room with correct scope should succeed.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() @@ -555,9 +531,8 @@ def test_api_rooms_create_success(settings): assert room.access_level == "trusted" -def test_api_rooms_create_readonly_enforcement(settings): +def test_api_rooms_create_readonly_enforcement(): """Creating a room succeeds and any provided read-only fields are ignored.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() @@ -590,9 +565,8 @@ def test_api_rooms_create_readonly_enforcement(settings): assert room.access_level == "trusted" -def test_api_rooms_unknown_actions(settings): +def test_api_rooms_unknown_actions(): """Updating or deleting a room are not supported yet.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() room = RoomFactory(users=[(user, RoleChoices.OWNER)]) @@ -623,7 +597,6 @@ def test_api_rooms_unknown_actions(settings): def test_api_rooms_response_no_url(settings): """Response should not include url field when APPLICATION_BASE_URL is None.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" settings.APPLICATION_BASE_URL = None user = UserFactory() @@ -642,7 +615,6 @@ def test_api_rooms_response_no_url(settings): def test_api_rooms_response_no_telephony(settings): """Response should not include telephony field when ROOM_TELEPHONY_ENABLED is False.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" settings.ROOM_TELEPHONY_ENABLED = False user = UserFactory() @@ -661,7 +633,6 @@ def test_api_rooms_response_no_telephony(settings): def test_api_rooms_token_scope_case_insensitive(settings): """Token's scope should be case-insensitive.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() application = ApplicationFactory() @@ -693,7 +664,6 @@ def test_api_rooms_token_scope_case_insensitive(settings): def test_api_rooms_token_without_delegated_flag(settings): """Token without delegated flag should be rejected.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() application = ApplicationFactory() @@ -726,7 +696,6 @@ def test_api_rooms_token_without_delegated_flag(settings): @mock.patch.object(ResourceServerAuthentication, "authenticate", return_value=None) def test_api_rooms_token_invalid_signature(mock_rs_authenticate, settings): """Token signed with an invalid key should defer to the next authentication.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() application = ApplicationFactory() @@ -759,7 +728,6 @@ def test_api_rooms_token_invalid_signature(mock_rs_authenticate, settings): @mock.patch.object(ResourceServerAuthentication, "authenticate", return_value=None) def test_api_rooms_token_invalid_alg(mock_rs_authenticate, settings): """Token signed with an invalid alg should defer to the next authentication.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" settings.APPLICATION_JWT_ALG = "RS256" user = UserFactory() @@ -791,7 +759,6 @@ def test_api_rooms_token_invalid_alg(mock_rs_authenticate, settings): def test_api_rooms_token_missing_client_id(settings): """Token without client_id should be rejected.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() now = datetime.now(timezone.utc) @@ -821,7 +788,6 @@ def test_api_rooms_token_missing_client_id(settings): def test_api_rooms_token_missing_user_id(settings): """Token without user_id should be rejected.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" application = ApplicationFactory() now = datetime.now(timezone.utc) @@ -851,7 +817,6 @@ def test_api_rooms_token_missing_user_id(settings): def test_api_rooms_token_invalid_audience(settings): """Token with an invalid audience should be rejected.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory() application = ApplicationFactory() @@ -882,7 +847,6 @@ def test_api_rooms_token_invalid_audience(settings): def test_api_rooms_token_unknown_user(settings): """Token for unknown user should be rejected.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" application = ApplicationFactory() now = datetime.now(timezone.utc) @@ -912,7 +876,6 @@ def test_api_rooms_token_unknown_user(settings): def test_api_rooms_token_unknown_application(settings): """Token for unknown application should be rejected.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" now = datetime.now(timezone.utc) payload = { @@ -941,7 +904,6 @@ def test_api_rooms_token_unknown_application(settings): def test_api_rooms_token_inactive_application(settings): """Token for inactive application should be rejected.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" application = ApplicationFactory(active=False) now = datetime.now(timezone.utc) diff --git a/src/backend/core/tests/test_external_api_token.py b/src/backend/core/tests/test_external_api_token.py index 0701f384..cc6a2278 100644 --- a/src/backend/core/tests/test_external_api_token.py +++ b/src/backend/core/tests/test_external_api_token.py @@ -21,7 +21,6 @@ pytestmark = pytest.mark.django_db def test_api_applications_generate_token_success(settings): """Valid credentials should return a JWT token.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" UserFactory(email="User.Family@example.com") application = ApplicationFactory( active=True, @@ -173,9 +172,8 @@ def test_api_applications_generate_token_domain_not_authorized(): assert "not authorized for this email domain" in str(response.data) -def test_api_applications_generate_token_domain_authorized(settings): +def test_api_applications_generate_token_domain_authorized(): """Application with domain authorization should succeed.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory(email="user@allowed.com") application = ApplicationFactory( active=True, @@ -230,7 +228,6 @@ def test_api_applications_generate_token_user_not_found(): @freeze_time("2023-01-15 12:00:00") def test_api_applications_token_payload_structure(settings): """Generated token should have correct payload structure.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory(email="user@example.com") application = ApplicationFactory( @@ -280,7 +277,6 @@ def test_api_applications_token_payload_structure(settings): def test_api_applications_token_new_user(settings): """Should create a new pending user when creation is allowed and user doesn't exist.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" settings.APPLICATION_ALLOW_USER_CREATION = True settings.OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION = True settings.OIDC_USER_SUB_FIELD_IMMUTABLE = False @@ -337,7 +333,6 @@ def test_api_applications_token_new_user(settings): def test_api_applications_token_existing_user(settings): """Application should not create a new user when user exist.""" - settings.APPLICATION_JWT_SECRET_KEY = "devKey" user = UserFactory(email="user@example.com") settings.APPLICATION_ALLOW_USER_CREATION = True diff --git a/src/backend/meet/settings.py b/src/backend/meet/settings.py index 6ba62dd1..eda28a76 100755 --- a/src/backend/meet/settings.py +++ b/src/backend/meet/settings.py @@ -917,6 +917,9 @@ class Test(Base): USE_SWAGGER = True EXTERNAL_API_ENABLED = True + APPLICATION_JWT_SECRET_KEY = "devKey" # noqa:S105 + APPLICATION_JWT_AUDIENCE = "Test inc." + CELERY_TASK_ALWAYS_EAGER = values.BooleanValue(True) def __init__(self):