fix: handle empty search results with page loop

This commit is contained in:
MontaGhanmy
2025-03-04 10:31:26 +01:00
committed by Anton Shepilov
parent 6f762ecefa
commit e1d48daba5
@@ -3,6 +3,7 @@ import { getLogger, logger, TdriveLogger } from "../../../core/platform/framewor
import { import {
CrudException, CrudException,
ListResult, ListResult,
Paginable,
Pagination, Pagination,
} from "../../../core/platform/framework/api/crud-service"; } from "../../../core/platform/framework/api/crud-service";
import Repository, { import Repository, {
@@ -1612,7 +1613,7 @@ export class DocumentsService {
/** /**
* Search for Drive items. * Search for Drive items.
* *
* @param {SearchDocumentsOptions} options - the search optins. * @param {SearchDocumentsOptions} options - the search options.
* @param {DriveExecutionContext} context - the execution context. * @param {DriveExecutionContext} context - the execution context.
* @returns {Promise<ListResult<DriveFile>>} - the search result. * @returns {Promise<ListResult<DriveFile>>} - the search result.
*/ */
@@ -1620,14 +1621,22 @@ export class DocumentsService {
options: SearchDocumentsOptions, options: SearchDocumentsOptions,
context?: DriveExecutionContext, context?: DriveExecutionContext,
): Promise<ListResult<DriveFile>> => { ): Promise<ListResult<DriveFile>> => {
let allResults: DriveFile[] = [];
let nextPage = options.pagination
? Pagination.fromPaginable(options.pagination)
: new Pagination();
let resultType: string | null = null; // Step 1: Declare before loop
// loop through all pages until we get results
do {
const result = await this.searchRepository.search( const result = await this.searchRepository.search(
{}, {},
{ {
pagination: options.pagination pagination: nextPage,
? Pagination.fromPaginable(options.pagination)
: new Pagination(),
$in: [ $in: [
...(options.onlyDirectlyShared ? [["access_entities", [context.user.id]] as inType] : []), ...(options.onlyDirectlyShared
? [["access_entities", [context.user.id]] as inType]
: []),
...(options.company_id ? [["company_id", [options.company_id]] as inType] : []), ...(options.company_id ? [["company_id", [options.company_id]] as inType] : []),
...(options.creator ? [["creator", [options.creator]] as inType] : []), ...(options.creator ? [["creator", [options.creator]] as inType] : []),
...(options.mime_type ...(options.mime_type
@@ -1639,7 +1648,9 @@ export class DocumentsService {
] ]
: []), : []),
], ],
$nin: [...(options.onlyUploadedNotByMe ? [["creator", [context.user.id]] as inType] : [])], $nin: [
...(options.onlyUploadedNotByMe ? [["creator", [context.user.id]] as inType] : []),
],
$lte: [ $lte: [
...(options.last_modified_lt ...(options.last_modified_lt
? [["last_modified", options.last_modified_lt] as comparisonType] ? [["last_modified", options.last_modified_lt] as comparisonType]
@@ -1664,11 +1675,20 @@ export class DocumentsService {
context, context,
); );
if (!resultType) {
resultType = result.type; // Capture type from the first result
}
let filteredResult = result.getEntities();
if (filteredResult.length === 0) {
break;
}
// if this flag is on, the access permissions were checked inside the database // if this flag is on, the access permissions were checked inside the database
if (!options.onlyDirectlyShared) { if (!options.onlyDirectlyShared) {
const filteredResult = await this.filter(result.getEntities(), async item => { filteredResult = await this.filter(filteredResult, async item => {
try { try {
//skip all the fiels
return ( return (
!item.is_in_trash && !item.is_in_trash &&
(await checkAccess(item.id, null, "read", this.repository, context)) (await checkAccess(item.id, null, "read", this.repository, context))
@@ -1678,18 +1698,19 @@ export class DocumentsService {
return false; return false;
} }
}); });
return new ListResult(result.type, filteredResult, result.nextPage);
} }
if (options.onlyUploadedNotByMe) { if (options.onlyUploadedNotByMe) {
const filteredResult = await this.filter(result.getEntities(), async item => { filteredResult = filteredResult.filter(
return item.creator != context.user.id && !item.is_in_trash; item => item.creator !== context.user.id && !item.is_in_trash,
}); );
return new ListResult(result.type, filteredResult, result.nextPage);
} }
return result;
allResults.push(...filteredResult);
nextPage = result.nextPage ? Pagination.fromPaginable(result.nextPage) : undefined;
} while (allResults.length === 0 && nextPage?.page_token); // Continue only if results are empty and there's a next page.
return new ListResult(resultType, allResults, nextPage);
}; };
private async filter(arr, callback) { private async filter(arr, callback) {