diff --git a/lib/types/sqlite-types.js b/lib/types/sqlite-types.js --- a/lib/types/sqlite-types.js +++ b/lib/types/sqlite-types.js @@ -80,6 +80,7 @@ dbID: DatabaseIdentifier, ) => Promise, +getHolders: (dbID: DatabaseIdentifier) => Promise, + +getAuxUserIDs: (dbID: DatabaseIdentifier) => Promise>, // write operations +removeInboundP2PMessages: (ids: $ReadOnlyArray) => Promise, diff --git a/lib/utils/__mocks__/config.js b/lib/utils/__mocks__/config.js --- a/lib/utils/__mocks__/config.js +++ b/lib/utils/__mocks__/config.js @@ -55,6 +55,7 @@ getSyncedMetadata: jest.fn(), getHolders: jest.fn(), removeLocalMessageInfos: jest.fn(), + getAuxUserIDs: jest.fn(), }, encryptedNotifUtilsAPI: { generateAESKey: jest.fn(), diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h @@ -268,6 +268,8 @@ jsi::Runtime &rt, bool includeNonLocalMessages, jsi::String dbID) override; + virtual jsi::Value + getAuxUserInfos(jsi::Runtime &rt, jsi::String dbID) override; virtual jsi::Value markPrekeysAsPublished(jsi::Runtime &rt) override; virtual jsi::Value getRelatedMessages(jsi::Runtime &rt, jsi::String messageID) override; diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp @@ -3186,6 +3186,43 @@ }); } +jsi::Value CommCoreModule::getAuxUserInfos(jsi::Runtime &rt, jsi::String dbID) { + DatabaseIdentifier identifier = stringToDatabaseIdentifier(dbID.utf8(rt)); + return createPromiseAsJSIValue( + rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { + taskType job = [=, &innerRt]() { + std::string error; + std::vector auxUserInfosVector; + try { + auxUserInfosVector = DatabaseManager::getQueryExecutor(identifier) + .getAllAuxUserInfos(); + } catch (std::system_error &e) { + error = e.what(); + } + + auto auxUserInfosVectorPtr = + std::make_shared>( + std::move(auxUserInfosVector)); + + this->jsInvoker_->invokeAsync([&innerRt, + error, + promise, + auxUserInfosVectorPtr, + auxUserStore = this->auxUserStore]() { + if (error.size()) { + promise->reject(error); + return; + } + jsi::Array jsiAuxUserInfos = + auxUserStore.parseDBDataStore(innerRt, auxUserInfosVectorPtr); + promise->resolve(std::move(jsiAuxUserInfos)); + }); + }; + GlobalDBSingleton::instance.scheduleOrRunCancellable( + job, promise, this->jsInvoker_); + }); +} + jsi::Value CommCoreModule::markPrekeysAsPublished(jsi::Runtime &rt) { return createPromiseAsJSIValue( rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp --- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp @@ -244,6 +244,9 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_removeLocalMessageInfos(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->removeLocalMessageInfos(rt, args[0].asBool(), args[1].asString(rt)); } +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getAuxUserInfos(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getAuxUserInfos(rt, args[0].asString(rt)); +} CommCoreModuleSchemaCxxSpecJSI::CommCoreModuleSchemaCxxSpecJSI(std::shared_ptr jsInvoker) : TurboModule("CommTurboModule", jsInvoker) { @@ -322,6 +325,7 @@ methodMap_["copyContentFromBackupDatabase"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_copyContentFromBackupDatabase}; methodMap_["getHolders"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getHolders}; methodMap_["removeLocalMessageInfos"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_removeLocalMessageInfos}; + methodMap_["getAuxUserInfos"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getAuxUserInfos}; } diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h --- a/native/cpp/CommonCpp/_generated/commJSI.h +++ b/native/cpp/CommonCpp/_generated/commJSI.h @@ -95,6 +95,7 @@ virtual jsi::Value copyContentFromBackupDatabase(jsi::Runtime &rt) = 0; virtual jsi::Value getHolders(jsi::Runtime &rt, jsi::String dbID) = 0; virtual jsi::Value removeLocalMessageInfos(jsi::Runtime &rt, bool includeNonLocalMessages, jsi::String dbID) = 0; + virtual jsi::Value getAuxUserInfos(jsi::Runtime &rt, jsi::String dbID) = 0; }; @@ -716,6 +717,14 @@ return bridging::callFromJs( rt, &T::removeLocalMessageInfos, jsInvoker_, instance_, std::move(includeNonLocalMessages), std::move(dbID)); } + jsi::Value getAuxUserInfos(jsi::Runtime &rt, jsi::String dbID) override { + static_assert( + bridging::getParameterCount(&T::getAuxUserInfos) == 2, + "Expected getAuxUserInfos(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::getAuxUserInfos, jsInvoker_, instance_, std::move(dbID)); + } private: T *instance_; diff --git a/native/database/sqlite-api.js b/native/database/sqlite-api.js --- a/native/database/sqlite-api.js +++ b/native/database/sqlite-api.js @@ -33,6 +33,10 @@ const dbHolders = await commCoreModule.getHolders(dbID); return holderStoreOpsHandlers.translateClientDBData(dbHolders); }, + async getAuxUserIDs(dbID: DatabaseIdentifier): Promise> { + const auxUserInfos = await commCoreModule.getAuxUserInfos(dbID); + return auxUserInfos.map(auxUserInfo => auxUserInfo.id); + }, // write operations removeInboundP2PMessages: commCoreModule.removeInboundP2PMessages, diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -5,6 +5,7 @@ import { TurboModuleRegistry } from 'react-native'; import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport.js'; +import type { ClientDBAuxUserInfo } from 'lib/ops/aux-user-store-ops.js'; import type { ClientDBDMOperation } from 'lib/ops/dm-operations-store-ops.js'; import type { ClientDBMessageStoreOperation } from 'lib/ops/message-store-ops.js'; import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js'; @@ -245,6 +246,9 @@ includeNonLocalMessages: boolean, dbID: string, ) => Promise; + +getAuxUserInfos: ( + dbID: string, + ) => Promise<$ReadOnlyArray>; } export interface CoreModuleSpec extends Spec { diff --git a/web/database/sqlite-api.js b/web/database/sqlite-api.js --- a/web/database/sqlite-api.js +++ b/web/database/sqlite-api.js @@ -1,5 +1,6 @@ // @flow +import type { ClientDBAuxUserInfo } from 'lib/ops/aux-user-store-ops.js'; import type { ClientDBDMOperation } from 'lib/ops/dm-operations-store-ops.js'; import { holderStoreOpsHandlers } from 'lib/ops/holder-store-ops.js'; import { convertStoreOperationsToClientDBStoreOperations } from 'lib/shared/redux/client-db-utils.js'; @@ -169,6 +170,17 @@ return holderStoreOpsHandlers.translateClientDBData(dbHolders); }, + async getAuxUserIDs(dbID: DatabaseIdentifier): Promise> { + const sharedWorker = await getCommSharedWorker(); + const data = await sharedWorker.schedule({ + type: workerRequestMessageTypes.GET_AUX_USER_INFOS, + dbID, + }); + const dbAuxUserInfos: $ReadOnlyArray = + data?.auxUserInfos ?? []; + return dbAuxUserInfos.map(item => item.id); + }, + // write operations async removeInboundP2PMessages(ids: $ReadOnlyArray): Promise { const sharedWorker = await getCommSharedWorker(); diff --git a/web/shared-worker/worker/shared-worker.js b/web/shared-worker/worker/shared-worker.js --- a/web/shared-worker/worker/shared-worker.js +++ b/web/shared-worker/worker/shared-worker.js @@ -478,6 +478,22 @@ type: workerResponseMessageTypes.GET_HOLDERS, holders: sqliteQueryExecutor.getHolders(), }; + } else if (message.type === workerRequestMessageTypes.GET_AUX_USER_INFOS) { + if (message.dbID && message.dbID === databaseIdentifier.RESTORED) { + const restoredQueryExecutor = getSQLiteQueryExecutorOrThrow( + databaseIdentifier.RESTORED, + message, + ); + return { + type: workerResponseMessageTypes.GET_AUX_USER_INFOS, + auxUserInfos: restoredQueryExecutor.getAllAuxUserInfos(), + }; + } + + return { + type: workerResponseMessageTypes.GET_AUX_USER_INFOS, + auxUserInfos: sqliteQueryExecutor.getAllAuxUserInfos(), + }; } // write operations diff --git a/web/types/worker-types.js b/web/types/worker-types.js --- a/web/types/worker-types.js +++ b/web/types/worker-types.js @@ -1,5 +1,6 @@ // @flow +import type { ClientDBAuxUserInfo } from 'lib/ops/aux-user-store-ops.js'; import type { ClientDBDMOperation } from 'lib/ops/dm-operations-store-ops.js'; import type { AuthMetadata } from 'lib/shared/identity-client-context.js'; import type { @@ -60,6 +61,7 @@ GET_SYNCED_METADATA: 31, GET_HOLDERS: 32, REMOVE_LOCAL_MESSAGE_INFOS: 33, + GET_AUX_USER_INFOS: 34, }); export const workerWriteRequests: $ReadOnlyArray = [ @@ -281,6 +283,11 @@ +dbID: DatabaseIdentifier, }; +export type GetAuxUserInfosRequestMessage = { + +type: 34, + +dbID: DatabaseIdentifier, +}; + export type WorkerRequestMessage = | PingWorkerRequestMessage | InitWorkerRequestMessage @@ -315,7 +322,8 @@ | GetDatabaseVersionRequestMessage | GetSyncedMetadataRequestMessage | GetHoldersRequestMessage - | RemoveLocalMessageInfosRequestMessage; + | RemoveLocalMessageInfosRequestMessage + | GetAuxUserInfosRequestMessage; export type WorkerRequestProxyMessage = { +id: number, @@ -338,6 +346,7 @@ GET_DATABASE_VERSION: 11, GET_SYNCED_METADATA: 12, GET_HOLDERS: 13, + GET_AUX_USER_INFOS: 14, }); export type PongWorkerResponseMessage = { @@ -410,6 +419,11 @@ +holders: $ReadOnlyArray, }; +export type GetAuxUserInfosResponseMessage = { + +type: 14, + +auxUserInfos: $ReadOnlyArray, +}; + export type WorkerResponseMessage = | PongWorkerResponseMessage | ClientStoreResponseMessage @@ -424,7 +438,8 @@ | DMOperationsResponseMessage | GetDatabaseVersionResponseMessage | GetSyncedMetadataResponseMessage - | GetHoldersResponseMessage; + | GetHoldersResponseMessage + | GetAuxUserInfosResponseMessage; export type WorkerResponseProxyMessage = { +id?: number,