fixup! 🚨(backend) fix search without refresh token

Signed-off-by: charles <charles.englebert@protonmail.com>
This commit is contained in:
charles
2026-03-20 11:57:10 +01:00
parent b4eb54305a
commit c0ecf53fbf
7 changed files with 88 additions and 15 deletions
+1
View File
@@ -36,6 +36,7 @@ and this project adheres to
- ♿️(frontend) fix waffle aria-label spacing for new-window links #2030
- 🐛(backend) stop using add_sibling method to create sandbox document #2084
- 🐛(backend) duplicate a document as last-sibling #2084
- 🐛(backend) fix search without refresh token #2090
### Removed
+1 -1
View File
@@ -198,7 +198,7 @@ def refresh_access_token(session):
"client_secret": settings.OIDC_RP_CLIENT_SECRET,
"refresh_token": refresh_token,
},
timeout=5,
timeout=settings.OIDC_TIMEOUT,
)
response.raise_for_status()
token_info = response.json()
+2 -10
View File
@@ -1429,15 +1429,6 @@ class DocumentViewSet(
if search_type == SearchType.TITLE:
return self._title_search(request, params.validated_data, *args, **kwargs)
try:
request.session = refresh_access_token(request.session)
except AuthenticationFailed:
logging.warning(
"User unauthenticated or error while refreshing token, "
"falling back to title search."
)
return self._title_search(request, params.validated_data, *args, **kwargs)
indexer = get_document_indexer()
if indexer is None:
# fallback on title search if the indexer is not configured
@@ -1447,7 +1438,7 @@ class DocumentViewSet(
return self._search_with_indexer(
indexer, request, params=params, search_type=search_type
)
except requests.exceptions.RequestException as e:
except (requests.exceptions.RequestException, AuthenticationFailed) as e:
logger.error(
"Error while searching documents with indexer \n%s \nfall back on title search",
e,
@@ -1473,6 +1464,7 @@ class DocumentViewSet(
"""
Returns a list of documents matching the query (q) according to the configured indexer.
"""
request.session = refresh_access_token(request.session)
queryset = models.Document.objects.all()
results = indexer.search(
+2 -2
View File
@@ -147,8 +147,8 @@ def user_token():
return build_authorization_bearer("some_token")
@pytest.fixture(name="oidc_settings")
def fixture_oidc_settings(settings):
@pytest.fixture
def oidc_settings(settings):
"""Fixture to configure OIDC settings for the tests."""
settings.OIDC_OP_TOKEN_ENDPOINT = "https://auth.example.com/token"
settings.OIDC_OP_AUTHORIZATION_ENDPOINT = "https://auth.example.com/authorize"
@@ -2,7 +2,6 @@
Tests for Documents API endpoint in impress's core app: search
"""
import re
from unittest import mock
from unittest.mock import patch
@@ -4,7 +4,6 @@ Tests for Find search feature flags
from unittest import mock
from django.contrib.sessions.backends.cache import SessionStore
from django.http import HttpResponse
import pytest
@@ -0,0 +1,82 @@
"""Unit tests for the refresh_access_token utility function."""
import pytest
import responses
from cryptography.fernet import Fernet
from lasuite.oidc_login.backends import get_oidc_refresh_token, store_tokens
from requests import HTTPError
from rest_framework.exceptions import AuthenticationFailed
from core.api.utils import refresh_access_token
pytestmark = pytest.mark.django_db
@pytest.fixture(name="mock_oidc_settings")
def mock_oidc_settings_fixture(settings):
"""Fixture to mock OIDC settings."""
settings.OIDC_OP_TOKEN_ENDPOINT = "https://example.com/token"
settings.OIDC_RP_CLIENT_ID = "test-client-id"
settings.OIDC_RP_CLIENT_SECRET = "test-client-secret"
settings.OIDC_STORE_REFRESH_TOKEN = True
settings.OIDC_STORE_REFRESH_TOKEN_KEY = Fernet.generate_key()
yield settings
@responses.activate
def test_refresh_access_token_success(mock_oidc_settings): # pylint: disable=unused-argument
"""Test successful token refresh."""
session = {}
store_tokens(
session,
access_token="old-access-token",
id_token=None,
refresh_token="valid-refresh-token",
)
responses.add(
responses.POST,
"https://example.com/token",
json={
"access_token": "new-access-token",
"refresh_token": "new-refresh-token",
},
status=200,
)
result = refresh_access_token(session)
assert result == session
assert get_oidc_refresh_token(session) == "new-refresh-token"
def test_refresh_access_token_missing_refresh_token(mock_oidc_settings): # pylint: disable=unused-argument
"""Test that AuthenticationFailed is raised when refresh token is missing."""
session = {}
with pytest.raises(AuthenticationFailed) as exc_info:
refresh_access_token(session)
assert exc_info.value.detail == {"error": "Refresh token is missing from session"}
@responses.activate
def test_refresh_access_token_http_error(mock_oidc_settings): # pylint: disable=unused-argument
"""Test that HTTP errors are propagated when token endpoint fails."""
session = {}
store_tokens(
session,
access_token="old-access-token",
id_token=None,
refresh_token="valid-refresh-token",
)
responses.add(
responses.POST,
"https://example.com/token",
json={"error": "invalid_grant"},
status=401,
)
with pytest.raises(HTTPError):
refresh_access_token(session)