Skip to content

Commit 508dc31

Browse files
committed
🚨(backend) various fixes
I am fixing various things Signed-off-by: charles <charles.englebert@protonmail.com>
1 parent 36cd61f commit 508dc31

File tree

10 files changed

+254
-287
lines changed

10 files changed

+254
-287
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,9 @@ $ make frontend-test
147147
$ make frontend-lint
148148
```
149149

150-
Backend tests can be run without docker by settings Path to ".env" file to
151-
`env.d/development/common.test`
150+
Backend tests can be run without docker with the env files
151+
`env.d/development/common` and `env.d/development/common.test`.
152+
`common.test` must overwrite some variables in `common`.
152153

153154
**Adding content**
154155

src/backend/core/api/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,5 +980,5 @@ def get_abilities(self, thread):
980980
class SearchDocumentSerializer(serializers.Serializer):
981981
"""Serializer for fulltext search requests through Find application"""
982982

983-
q = serializers.CharField(required=True, allow_blank=False, trim_whitespace=True)
983+
q = serializers.CharField(required=True, allow_blank=True, trim_whitespace=True)
984984
path = serializers.CharField(required=False, allow_blank=False)

src/backend/core/api/viewsets.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,6 @@ def duplicate(self, request, *args, **kwargs):
11651165
{"id": str(duplicated_document.id)}, status=status.HTTP_201_CREATED
11661166
)
11671167

1168-
11691168
@drf.decorators.action(detail=False, methods=["get"], url_path="search")
11701169
@method_decorator(refresh_oidc_access_token)
11711170
def search(self, request, *args, **kwargs):
@@ -1218,12 +1217,15 @@ def _search_with_indexer(indexer, request, params):
12181217
)
12191218

12201219
def title_search(self, request, validated_data, *args, **kwargs):
1220+
"""
1221+
Fallback search by title when indexer is not configured.
1222+
If path is provided, list descendants, otherwise list all documents.
1223+
"""
12211224
request.GET = request.GET.copy()
1222-
request.GET['title'] = validated_data['q']
1223-
if not "path" in validated_data or not validated_data["path"]:
1225+
request.GET["title"] = validated_data["q"]
1226+
if not "path" in request.GET or not request.GET["path"]:
12241227
return self.list(request, *args, **kwargs)
1225-
else:
1226-
return self._list_descendants(request)
1228+
return self._list_descendants(request)
12271229

12281230
def _list_descendants(self, request):
12291231
"""
@@ -1236,15 +1238,17 @@ def _list_descendants(self, request):
12361238
try:
12371239
parent = models.Document.objects.get(path=parent_path)
12381240
except models.Document.DoesNotExist as exc:
1239-
raise drf.exceptions.NotFound("Document not found from path %s.", parent_path) from exc
1241+
raise drf.exceptions.NotFound("Document not found from path.") from exc
12401242

12411243
# Check object-level permissions using DocumentPermission logic
12421244
self.check_object_permissions(request, parent)
12431245

12441246
# Get descendants and include the parent, ordered by path
1245-
queryset = parent.get_descendants(include_self=True).filter(
1246-
ancestors_deleted_at__isnull=True
1247-
).order_by("path")
1247+
queryset = (
1248+
parent.get_descendants(include_self=True)
1249+
.filter(ancestors_deleted_at__isnull=True)
1250+
.order_by("path")
1251+
)
12481252
queryset = self.filter_queryset(queryset)
12491253

12501254
# filter by title
@@ -1255,7 +1259,6 @@ def _list_descendants(self, request):
12551259
queryset = filterset.qs
12561260
return self.get_response_for_queryset(queryset)
12571261

1258-
12591262
@drf.decorators.action(detail=True, methods=["get"], url_path="versions")
12601263
def versions_list(self, request, *args, **kwargs):
12611264
"""

src/backend/core/services/search_indexers.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from django.conf import settings
99
from django.contrib.auth.models import AnonymousUser
1010
from django.core.exceptions import ImproperlyConfigured
11-
from django.db.models import Subquery
1211
from django.utils.module_loading import import_string
1312

1413
import requests
@@ -78,15 +77,17 @@ def get_visited_document_ids_of(queryset, user):
7877
if isinstance(user, AnonymousUser):
7978
return []
8079

81-
qs = models.LinkTrace.objects.filter(user=user)
80+
visited_ids = models.LinkTrace.objects.filter(user=user).values_list(
81+
"document_id", flat=True
82+
)
8283

8384
docs = (
8485
queryset.exclude(accesses__user=user)
8586
.filter(
8687
deleted_at__isnull=True,
8788
ancestors_deleted_at__isnull=True,
8889
)
89-
.filter(pk__in=Subquery(qs.values("document_id")))
90+
.filter(pk__in=visited_ids)
9091
.order_by("pk")
9192
.distinct("pk")
9293
)
@@ -193,7 +194,7 @@ def search(self, q, token, visited=(), nb_results=None, path=None):
193194
Returns ids of the documents
194195
195196
Args:
196-
q (str): Text search content.
197+
q (str): user query.
197198
token (str): OIDC Authentication token.
198199
visited (list, optional):
199200
List of ids of active public documents with LinkTrace
@@ -202,7 +203,7 @@ def search(self, q, token, visited=(), nb_results=None, path=None):
202203
The number of results to return.
203204
Defaults to 50 if not specified.
204205
path (str, optional):
205-
The path to filter documents.
206+
The parent path to search descendants of.
206207
"""
207208
nb_results = nb_results or self.search_limit
208209
results = self.search_query(
@@ -231,25 +232,27 @@ def search_query(self, data, token) -> dict:
231232

232233
class FindDocumentIndexer(BaseDocumentIndexer):
233234
"""
234-
Document indexer that indexes and searches documents to La Suite Find app.
235+
Document indexer that indexes and searches documents with La Suite Find app.
235236
"""
236237

238+
# pylint: disable=too-many-arguments,too-many-positional-arguments
237239
def search(self, q, token, visited=(), nb_results=None, path=None):
238240
"""format Find search results"""
239241
search_results = super().search(q, token, visited, nb_results, path)
240242
return [
241243
{
244+
**hit["_source"],
242245
"id": hit["_id"],
243246
"title": self.get_title(hit["_source"]),
244-
**hit["_source"],
245247
}
246248
for hit in search_results
247249
]
248250

249251
@staticmethod
250252
def get_title(source):
251253
"""
252-
Extract the title from a search result source dictionary.
254+
Find returns the titles with an extension depending on the language.
255+
This function extracts the title in a generic way.
253256
254257
Handles multiple cases:
255258
- Localized title fields like "title.<some_extension>"
@@ -271,13 +274,12 @@ def get_title(source):
271274
""
272275
"""
273276
titles = utils.get_value_by_pattern(source, r"^title\.")
274-
if titles:
275-
title = titles[0]
276-
elif "title" in source:
277-
title = source["title"]
278-
else:
279-
title = ""
280-
return title
277+
for title in titles:
278+
if title:
279+
return title
280+
if "title" in source:
281+
return source["title"]
282+
return ""
281283

282284
def serialize_document(self, document, accesses):
283285
"""

src/backend/core/tests/documents/test_api_documents_descendants_filters.py

Lines changed: 0 additions & 95 deletions
This file was deleted.

0 commit comments

Comments
 (0)