fix: handle empty search results with page loop
This commit is contained in:
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,76 +1621,96 @@ export class DocumentsService {
|
|||||||
options: SearchDocumentsOptions,
|
options: SearchDocumentsOptions,
|
||||||
context?: DriveExecutionContext,
|
context?: DriveExecutionContext,
|
||||||
): Promise<ListResult<DriveFile>> => {
|
): Promise<ListResult<DriveFile>> => {
|
||||||
const result = await this.searchRepository.search(
|
let allResults: DriveFile[] = [];
|
||||||
{},
|
let nextPage = options.pagination
|
||||||
{
|
? Pagination.fromPaginable(options.pagination)
|
||||||
pagination: options.pagination
|
: new Pagination();
|
||||||
? Pagination.fromPaginable(options.pagination)
|
let resultType: string | null = null; // Step 1: Declare before loop
|
||||||
: new Pagination(),
|
|
||||||
$in: [
|
|
||||||
...(options.onlyDirectlyShared ? [["access_entities", [context.user.id]] as inType] : []),
|
|
||||||
...(options.company_id ? [["company_id", [options.company_id]] as inType] : []),
|
|
||||||
...(options.creator ? [["creator", [options.creator]] as inType] : []),
|
|
||||||
...(options.mime_type
|
|
||||||
? [
|
|
||||||
[
|
|
||||||
"mime_type",
|
|
||||||
Array.isArray(options.mime_type) ? options.mime_type : [options.mime_type],
|
|
||||||
] as inType,
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
],
|
|
||||||
$nin: [...(options.onlyUploadedNotByMe ? [["creator", [context.user.id]] as inType] : [])],
|
|
||||||
$lte: [
|
|
||||||
...(options.last_modified_lt
|
|
||||||
? [["last_modified", options.last_modified_lt] as comparisonType]
|
|
||||||
: []),
|
|
||||||
...(options.added_lt ? [["added", options.added_lt] as comparisonType] : []),
|
|
||||||
],
|
|
||||||
$gte: [
|
|
||||||
...(options.last_modified_gt
|
|
||||||
? [["last_modified", options.last_modified_gt] as comparisonType]
|
|
||||||
: []),
|
|
||||||
...(options.added_gt ? [["added", options.added_gt] as comparisonType] : []),
|
|
||||||
],
|
|
||||||
...(options.search
|
|
||||||
? {
|
|
||||||
$text: {
|
|
||||||
$search: options.search,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
...(options.sort ? { $sort: options.sort } : {}),
|
|
||||||
},
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
|
|
||||||
// if this flag is on, the access permissions were checked inside the database
|
// loop through all pages until we get results
|
||||||
if (!options.onlyDirectlyShared) {
|
do {
|
||||||
const filteredResult = await this.filter(result.getEntities(), async item => {
|
const result = await this.searchRepository.search(
|
||||||
try {
|
{},
|
||||||
//skip all the fiels
|
{
|
||||||
return (
|
pagination: nextPage,
|
||||||
!item.is_in_trash &&
|
$in: [
|
||||||
(await checkAccess(item.id, null, "read", this.repository, context))
|
...(options.onlyDirectlyShared
|
||||||
);
|
? [["access_entities", [context.user.id]] as inType]
|
||||||
} catch (error) {
|
: []),
|
||||||
this.logger.warn("failed to check item access", error);
|
...(options.company_id ? [["company_id", [options.company_id]] as inType] : []),
|
||||||
return false;
|
...(options.creator ? [["creator", [options.creator]] as inType] : []),
|
||||||
}
|
...(options.mime_type
|
||||||
});
|
? [
|
||||||
|
[
|
||||||
|
"mime_type",
|
||||||
|
Array.isArray(options.mime_type) ? options.mime_type : [options.mime_type],
|
||||||
|
] as inType,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
],
|
||||||
|
$nin: [
|
||||||
|
...(options.onlyUploadedNotByMe ? [["creator", [context.user.id]] as inType] : []),
|
||||||
|
],
|
||||||
|
$lte: [
|
||||||
|
...(options.last_modified_lt
|
||||||
|
? [["last_modified", options.last_modified_lt] as comparisonType]
|
||||||
|
: []),
|
||||||
|
...(options.added_lt ? [["added", options.added_lt] as comparisonType] : []),
|
||||||
|
],
|
||||||
|
$gte: [
|
||||||
|
...(options.last_modified_gt
|
||||||
|
? [["last_modified", options.last_modified_gt] as comparisonType]
|
||||||
|
: []),
|
||||||
|
...(options.added_gt ? [["added", options.added_gt] as comparisonType] : []),
|
||||||
|
],
|
||||||
|
...(options.search
|
||||||
|
? {
|
||||||
|
$text: {
|
||||||
|
$search: options.search,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...(options.sort ? { $sort: options.sort } : {}),
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
|
||||||
return new ListResult(result.type, filteredResult, result.nextPage);
|
if (!resultType) {
|
||||||
}
|
resultType = result.type; // Capture type from the first result
|
||||||
|
}
|
||||||
|
|
||||||
if (options.onlyUploadedNotByMe) {
|
let filteredResult = result.getEntities();
|
||||||
const filteredResult = await this.filter(result.getEntities(), async item => {
|
|
||||||
return item.creator != context.user.id && !item.is_in_trash;
|
|
||||||
});
|
|
||||||
|
|
||||||
return new ListResult(result.type, filteredResult, result.nextPage);
|
if (filteredResult.length === 0) {
|
||||||
}
|
break;
|
||||||
return result;
|
}
|
||||||
|
|
||||||
|
// if this flag is on, the access permissions were checked inside the database
|
||||||
|
if (!options.onlyDirectlyShared) {
|
||||||
|
filteredResult = await this.filter(filteredResult, async item => {
|
||||||
|
try {
|
||||||
|
return (
|
||||||
|
!item.is_in_trash &&
|
||||||
|
(await checkAccess(item.id, null, "read", this.repository, context))
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.warn("failed to check item access", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.onlyUploadedNotByMe) {
|
||||||
|
filteredResult = filteredResult.filter(
|
||||||
|
item => item.creator !== context.user.id && !item.is_in_trash,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user