Compare commits

..

2 Commits

Author SHA1 Message Date
charles 1bfad9837c ♻️(backend) improve code
- move search_type default logic into the schemas to
simplify the view
- add logs
- remove redundant ResourceServerAuthentication
this authentication_classes is already in ResourceServerMixin
2026-03-23 17:08:56 +01:00
charles 8c31dd9221 🐛(backend) fix SearchTypeEnum
i used incoherent values between Find and Docs in SearchTypeEnum
2026-03-23 17:08:56 +01:00
6 changed files with 48 additions and 32 deletions
+1
View File
@@ -42,3 +42,4 @@ and this project adheres to
- 🐛(backend) fix missing index creation in 'index/' view
- 🐛(backend) fix parallel test execution issues
- 🐛(backend) fix search type value #68
+1 -1
View File
@@ -20,7 +20,7 @@ class SearchTypeEnum(str, Enum):
"""Search type options"""
HYBRID = "hybrid"
FULL_TEXT = "full_text"
FULL_TEXT = "full-text"
# Fields
+17 -2
View File
@@ -18,7 +18,7 @@ from pydantic import (
)
from . import enums
from .enums import SearchTypeEnum
from .services.opensearch import check_hybrid_search_enabled
class DocumentSchema(BaseModel):
@@ -119,7 +119,22 @@ class SearchQueryParametersSchema(BaseModel):
order_by: Optional[Literal[enums.ORDER_BY_OPTIONS]] = Field(default=enums.RELEVANCE)
order_direction: Optional[Literal["asc", "desc"]] = Field(default="desc")
nb_results: Optional[conint(ge=1, le=300)] = Field(default=50)
search_type: Optional[SearchTypeEnum] = Field(default=None)
search_type: Optional[enums.SearchTypeEnum] = None
@model_validator(mode="after")
def set_default_search_type(self):
"""
Set default search_type dynamically.
If search_type is not provided, it will be set to hybrid if it is configured
and fall back on full text otherwise.
"""
if self.search_type is None:
self.search_type = (
enums.SearchTypeEnum.HYBRID
if check_hybrid_search_enabled()
else enums.SearchTypeEnum.FULL_TEXT
)
return self
class DeleteDocumentsSchema(BaseModel):
@@ -94,7 +94,7 @@ def test_api_documents_search_opensearch_env_variables_not_set(settings):
@responses.activate
def test_api_documents_search_query_unknown_user(settings):
"""Searching a document without an existing user should result in a 401 error"""
"""Searching a document without an existing user should result in a 400 error"""
setup_oicd_resource_server(
responses,
settings,
+9 -9
View File
@@ -12,14 +12,13 @@ from rest_framework.response import Response
from . import schemas
from .authentication import ServiceTokenAuthentication
from .enums import SearchTypeEnum
from .permissions import IsAuthAuthenticated
from .services.indexing import (
ensure_index_exists,
get_opensearch_indices,
prepare_document_for_indexing,
)
from .services.opensearch import check_hybrid_search_enabled, opensearch_client
from .services.opensearch import opensearch_client
from .services.search import search
from .utils import get_language_value
@@ -306,7 +305,6 @@ class SearchDocumentView(ResourceServerMixin, views.APIView):
- The search results can be sorted or filtered via querystring parameters.
"""
authentication_classes = [ResourceServerAuthentication]
permission_classes = [IsAuthAuthenticated]
def post(self, request, *args, **kwargs):
@@ -365,7 +363,13 @@ class SearchDocumentView(ResourceServerMixin, views.APIView):
audience = self._get_service_provider_audience()
user_sub = self.request.user.sub
groups = []
params = schemas.SearchQueryParametersSchema(**request.data)
try:
params = schemas.SearchQueryParametersSchema(**request.data)
except PydanticValidationError as excpt:
errors = {error["loc"][0]: error["msg"] for error in excpt.errors()}
logger.error("Validation error: %s", errors)
raise excpt
# Get index list for search query
try:
@@ -390,11 +394,7 @@ class SearchDocumentView(ResourceServerMixin, views.APIView):
groups=groups,
tags=params.tags,
path=params.path,
search_type=params.search_type
if params.search_type
else SearchTypeEnum.HYBRID
if check_hybrid_search_enabled()
else SearchTypeEnum.FULL_TEXT,
search_type=params.search_type,
)["hits"]["hits"]
logger.info("found %d results", len(result))
logger.debug("results %s", result)
+19 -19
View File
@@ -23,31 +23,31 @@ description = "An application to print markdown to pdf from a set of managed tem
keywords = ["Django", "Contacts", "Templates", "RBAC"]
license = { file = "LICENSE" }
readme = "README.md"
requires-python = "~=3.14.3"
requires-python = "~=3.12.0"
dependencies = [
"celery[redis]==5.6.2",
"django-configurations==2.5.1",
"django-cors-headers==4.9.0",
"redis==7.3.0",
"redis==5.3.1",
"django-redis==6.0.0",
"django==6.0.3",
"django-lasuite[all]==0.0.25",
"django==5.2.12",
"django-lasuite[all]==0.0.22",
"djangorestframework==3.16.1",
"drf_spectacular==0.29.0",
"dockerflow==2026.3.4",
"dockerflow==2024.4.2",
"factory_boy==3.3.3",
"gunicorn==25.1.0",
"gunicorn==23.0.0",
"py3langid==0.3.0",
"langchain-text-splitters==1.1.1",
"langchain-text-splitters==1.1.0",
"mozilla-django-oidc==5.0.2",
"psycopg[binary]==3.3.3",
"psycopg[binary]==3.3.2",
"pydantic==2.12.5",
"pyjwt==2.10.1",
"requests==2.32.5",
"sentry-sdk==2.54.0",
"sentry-sdk==2.48.0",
"url-normalize==2.2.1",
"opensearch-py==3.1.0",
"whitenoise==6.12.0",
"whitenoise==6.11.0",
]
[project.urls]
@@ -59,21 +59,21 @@ dependencies = [
[project.optional-dependencies]
dev = [
"django-extensions==4.1",
"drf-spectacular-sidecar==2026.3.1",
"faker==40.11.0",
"drf-spectacular-sidecar==2026.1.1",
"faker==40.1.0",
"ipdb==0.13.13",
"ipython==9.11.0",
"pyfakefs==6.1.5",
"ipython==9.8.0",
"pyfakefs==6.0.0",
"pylint-django==2.7.0",
"pylint==4.0.5",
"pylint==4.0.4",
"pytest-cov==7.0.0",
"pytest-django==4.12.0",
"pytest-django==4.11.1",
"pytest==9.0.2",
"pytest-icdiff==0.9",
"pytest-xdist==3.8.0",
"responses==0.26.0",
"ruff==0.15.6",
"types-requests==2.32.4.20260107",
"responses==0.25.8",
"ruff==0.14.10",
"types-requests==2.32.4.20250913",
]
[tool.setuptools]