diff --git a/native/cpp/CommonCpp/NativeModules/AuxUserStoreOperations.h b/native/cpp/CommonCpp/NativeModules/AuxUserStoreOperations.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/AuxUserStoreOperations.h @@ -0,0 +1,48 @@ +#pragma once + +#include "../DatabaseManagers/entities/AuxUserInfo.h" +#include "DatabaseManager.h" +#include + +namespace comm { +class AuxUserStoreOperationBase { +public: + virtual void execute() = 0; + virtual ~AuxUserStoreOperationBase(){}; +}; + +class RemoveAuxUserInfosOperation : public AuxUserStoreOperationBase { +public: + RemoveAuxUserInfosOperation(std::vector ids) : ids{ids} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeAuxUserInfos(this->ids); + } + +private: + std::vector ids; +}; + +class ReplaceAuxUserInfoOperation : public AuxUserStoreOperationBase { +public: + ReplaceAuxUserInfoOperation(AuxUserInfo &&auxUserInfo) + : auxUserInfo{std::move(auxUserInfo)} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().replaceAuxUserInfo(this->auxUserInfo); + } + +private: + AuxUserInfo auxUserInfo; +}; + +class RemoveAllAuxUserInfosOperation : public AuxUserStoreOperationBase { +public: + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeAllAuxUserInfos(); + } +}; + +} // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/CMakeLists.txt b/native/cpp/CommonCpp/NativeModules/CMakeLists.txt --- a/native/cpp/CommonCpp/NativeModules/CMakeLists.txt +++ b/native/cpp/CommonCpp/NativeModules/CMakeLists.txt @@ -22,6 +22,7 @@ "CommunityStoreOperations.h" "IntegrityStoreOperations.h" "SyncedMetadataStoreOperations.h" + "AuxUserStoreOperations.h" ) set(NATIVE_SRCS @@ -87,6 +88,7 @@ ${_data_stores_path}/CommunityStore.h ${_data_stores_path}/IntegrityStore.h ${_data_stores_path}/SyncedMetadataStore.h + ${_data_stores_path}/AuxUserStore.h ) set(DATA_STORES_SRCS ${_data_stores_path}/DraftStore.cpp @@ -98,6 +100,7 @@ ${_data_stores_path}/CommunityStore.cpp ${_data_stores_path}/IntegrityStore.cpp ${_data_stores_path}/SyncedMetadataStore.cpp + ${_data_stores_path}/AuxUserStore.cpp ) set(_backup_op_path ./PersistentStorageUtilities/BackupOperationsUtilities) 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 @@ -5,6 +5,7 @@ #include "../Tools/CommSecureStore.h" #include "../Tools/WorkerThread.h" #include "../_generated/commJSI.h" +#include "PersistentStorageUtilities/DataStores/AuxUserStore.h" #include "PersistentStorageUtilities/DataStores/CommunityStore.h" #include "PersistentStorageUtilities/DataStores/DraftStore.h" #include "PersistentStorageUtilities/DataStores/IntegrityStore.h" @@ -41,6 +42,7 @@ CommunityStore communityStore; IntegrityStore integrityStore; SyncedMetadataStore syncedMetadataStore; + AuxUserStore auxUserStore; void persistCryptoModules(bool persistContentModule, bool persistNotifsModule); @@ -88,6 +90,9 @@ virtual jsi::Value processSyncedMetadataStoreOperations( jsi::Runtime &rt, jsi::Array operations) override; + virtual jsi::Value processAuxUserStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) override; virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) override; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) override; virtual jsi::Value 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 @@ -368,6 +368,12 @@ rt, std::move(operations)); } +jsi::Value CommCoreModule::processAuxUserStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) { + return this->auxUserStore.processStoreOperations(rt, std::move(operations)); +} + void CommCoreModule::terminate(jsi::Runtime &rt) { TerminateApp::terminate(); } @@ -1348,7 +1354,8 @@ keyserverStore(jsInvoker), communityStore(jsInvoker), integrityStore(jsInvoker), - syncedMetadataStore(jsInvoker) { + syncedMetadataStore(jsInvoker), + auxUserStore(jsInvoker) { GlobalDBSingleton::instance.enableMultithreading(); } diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/AuxUserStore.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/AuxUserStore.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/AuxUserStore.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../../../DatabaseManagers/entities/AuxUserInfo.h" +#include "AuxUserStoreOperations.h" +#include "BaseDataStore.h" + +#include + +namespace comm { + +class AuxUserStore + : public BaseDataStore { +private: + static OperationType REMOVE_OPERATION; + static OperationType REMOVE_ALL_OPERATION; + static OperationType REPLACE_OPERATION; + +public: + AuxUserStore(std::shared_ptr jsInvoker); + + std::vector> createOperations( + jsi::Runtime &rt, + const jsi::Array &operations) const override; + + jsi::Array parseDBDataStore( + jsi::Runtime &rt, + std::shared_ptr> dataVectorPtr) const override; +}; + +} // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/AuxUserStore.cpp b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/AuxUserStore.cpp new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/AuxUserStore.cpp @@ -0,0 +1,67 @@ +#include "AuxUserStore.h" + +#include +#include + +namespace comm { + +OperationType AuxUserStore::REMOVE_OPERATION = "remove_aux_user_infos"; +OperationType AuxUserStore::REMOVE_ALL_OPERATION = "remove_all_aux_user_infos"; +OperationType AuxUserStore::REPLACE_OPERATION = "replace_aux_user_info"; + +AuxUserStore::AuxUserStore( + std::shared_ptr jsInvoker) + : BaseDataStore(jsInvoker) { +} + +jsi::Array AuxUserStore::parseDBDataStore( + jsi::Runtime &rt, + std::shared_ptr> auxUserInfosVectorPtr) const { + jsi::Array jsiAuxUserInfos = jsi::Array(rt, 0); + return jsiAuxUserInfos; +} + +std::vector> +AuxUserStore::createOperations(jsi::Runtime &rt, const jsi::Array &operations) + const { + std::vector> auxUserStoreOps; + + for (size_t idx = 0; idx < operations.size(rt); idx++) { + jsi::Object op = operations.getValueAtIndex(rt, idx).asObject(rt); + std::string opType = op.getProperty(rt, "type").asString(rt).utf8(rt); + + if (opType == REMOVE_OPERATION) { + std::vector auxUserIDsToRemove; + jsi::Object payloadObj = op.getProperty(rt, "payload").asObject(rt); + jsi::Array auxUserIDs = + payloadObj.getProperty(rt, "ids").asObject(rt).asArray(rt); + for (int auxUserInfoIdx = 0; auxUserInfoIdx < auxUserIDs.size(rt); + auxUserInfoIdx++) { + auxUserIDsToRemove.push_back( + auxUserIDs.getValueAtIndex(rt, auxUserInfoIdx) + .asString(rt) + .utf8(rt)); + } + auxUserStoreOps.push_back(std::make_unique( + std::move(auxUserIDsToRemove))); + } else if (opType == REMOVE_ALL_OPERATION) { + auxUserStoreOps.push_back( + std::make_unique()); + } else if (opType == REPLACE_OPERATION) { + jsi::Object payloadObj = op.getProperty(rt, "payload").asObject(rt); + std::string id = payloadObj.getProperty(rt, "id").asString(rt).utf8(rt); + std::string aux_user_info = + payloadObj.getProperty(rt, "auxUserInfo").asString(rt).utf8(rt); + + AuxUserInfo auxUserInfo{id, aux_user_info}; + + auxUserStoreOps.push_back(std::make_unique( + std::move(auxUserInfo))); + } else { + throw std::runtime_error("unsupported operation: " + opType); + } + }; + return auxUserStoreOps; +} + +} // namespace comm 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 @@ -72,6 +72,9 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processSyncedMetadataStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->processSyncedMetadataStoreOperations(rt, args[0].asObject(rt).asArray(rt)); } +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processAuxUserStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->processAuxUserStoreOperations(rt, args[0].asObject(rt).asArray(rt)); +} static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->initializeCryptoAccount(rt); } @@ -206,6 +209,7 @@ methodMap_["processCommunityStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processCommunityStoreOperations}; methodMap_["processIntegrityStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processIntegrityStoreOperations}; methodMap_["processSyncedMetadataStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processSyncedMetadataStoreOperations}; + methodMap_["processAuxUserStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processAuxUserStoreOperations}; methodMap_["initializeCryptoAccount"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount}; methodMap_["getUserPublicKey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserPublicKey}; methodMap_["getOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getOneTimeKeys}; 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 @@ -39,6 +39,7 @@ virtual jsi::Value processCommunityStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value processIntegrityStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value processSyncedMetadataStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; + virtual jsi::Value processAuxUserStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; virtual jsi::Value getOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; @@ -248,6 +249,14 @@ return bridging::callFromJs( rt, &T::processSyncedMetadataStoreOperations, jsInvoker_, instance_, std::move(operations)); } + jsi::Value processAuxUserStoreOperations(jsi::Runtime &rt, jsi::Array operations) override { + static_assert( + bridging::getParameterCount(&T::processAuxUserStoreOperations) == 2, + "Expected processAuxUserStoreOperations(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::processAuxUserStoreOperations, jsInvoker_, instance_, std::move(operations)); + } jsi::Value initializeCryptoAccount(jsi::Runtime &rt) override { static_assert( bridging::getParameterCount(&T::initializeCryptoAccount) == 1, diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj --- a/native/ios/Comm.xcodeproj/project.pbxproj +++ b/native/ios/Comm.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 1F537ACC7B60DC049C0ECFA7 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 769A87FB41BCE3FEF97FD59A /* ExpoModulesProvider.swift */; }; 34055C152BAD31AC0008E713 /* SyncedMetadataStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34055C142BAD31AC0008E713 /* SyncedMetadataStore.cpp */; }; 34329B442B9EC7EC00233438 /* IntegrityStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34329B3F2B9EBFCE00233438 /* IntegrityStore.cpp */; }; + 34FF25BA2BB757870075EC40 /* AuxUserStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34FF25B92BB757860075EC40 /* AuxUserStore.cpp */; }; 71142A7726C2650B0039DCBD /* CommSecureStoreIOSWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71142A7626C2650A0039DCBD /* CommSecureStoreIOSWrapper.mm */; }; 711B408425DA97F9005F8F06 /* dummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F26E81B24440D87004049C6 /* dummy.swift */; }; 71762A75270D8AAE00F565ED /* PlatformSpecificTools.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71762A74270D8AAE00F565ED /* PlatformSpecificTools.mm */; }; @@ -147,6 +148,9 @@ 34329B3F2B9EBFCE00233438 /* IntegrityStore.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = IntegrityStore.cpp; path = PersistentStorageUtilities/DataStores/IntegrityStore.cpp; sourceTree = ""; }; 34329B402B9EBFCE00233438 /* IntegrityStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IntegrityStore.h; path = PersistentStorageUtilities/DataStores/IntegrityStore.h; sourceTree = ""; }; 34329B452B9EC96200233438 /* IntegrityThreadHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntegrityThreadHash.h; sourceTree = ""; }; + 34FF25A62BB738DC0075EC40 /* AuxUserStoreOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuxUserStoreOperations.h; sourceTree = ""; }; + 34FF25B82BB753B30075EC40 /* AuxUserStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuxUserStore.h; path = PersistentStorageUtilities/DataStores/AuxUserStore.h; sourceTree = ""; }; + 34FF25B92BB757860075EC40 /* AuxUserStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AuxUserStore.cpp; path = PersistentStorageUtilities/DataStores/AuxUserStore.cpp; sourceTree = ""; }; 3EE4DCB430B05EC9DE7D7B01 /* libPods-NotificationService.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NotificationService.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 3EEB3E70587B0ADAD05237B0 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Comm/ExpoModulesProvider.swift"; sourceTree = ""; }; 71142A7526C2650A0039DCBD /* CommSecureStoreIOSWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommSecureStoreIOSWrapper.h; path = Comm/CommSecureStoreIOSWrapper.h; sourceTree = ""; }; @@ -495,6 +499,7 @@ 34055C162BAD31BD0008E713 /* SyncedMetadataStoreOperations.h */, B7055C6B26E477CF00BE0548 /* MessageStoreOperations.h */, B7906F692720905A009BBBF5 /* ThreadStoreOperations.h */, + 34FF25A62BB738DC0075EC40 /* AuxUserStoreOperations.h */, ); path = NativeModules; sourceTree = ""; @@ -652,6 +657,8 @@ 8EA59BD02A6E786200EB4F53 /* DataStores */ = { isa = PBXGroup; children = ( + 34FF25B82BB753B30075EC40 /* AuxUserStore.h */, + 34FF25B92BB757860075EC40 /* AuxUserStore.cpp */, 8E2CC2582B5C99B0000C94D6 /* KeyserverStore.cpp */, 8E2CC2572B5C99B0000C94D6 /* KeyserverStore.h */, B3B02EBD2B8536560020D118 /* CommunityStore.cpp */, @@ -1144,6 +1151,7 @@ CBCA09062A8E0E7400F75B3E /* StaffUtils.cpp in Sources */, 8EF7756B2A7433630046A385 /* ThreadStore.cpp in Sources */, CB2689002A2DF58000EC7300 /* CommConstants.cpp in Sources */, + 34FF25BA2BB757870075EC40 /* AuxUserStore.cpp in Sources */, CB7EF17E295C674300B17035 /* CommIOSNotifications.mm in Sources */, CB7EF180295C674300B17035 /* CommIOSNotificationsBridgeQueue.mm in Sources */, 7F0C6E31291C4468002AA2D9 /* ExpoModulesProvider.swift in Sources */, 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 { ClientDBAuxUserStoreOperation } from 'lib/ops/aux-user-store-ops.js'; import type { ClientDBCommunityStoreOperation } from 'lib/ops/community-store-ops.js'; import type { ClientDBIntegrityStoreOperation } from 'lib/ops/integrity-store-ops.js'; import type { ClientDBKeyserverStoreOperation } from 'lib/ops/keyserver-store-ops'; @@ -74,6 +75,9 @@ +processSyncedMetadataStoreOperations: ( operations: $ReadOnlyArray, ) => Promise; + +processAuxUserStoreOperations: ( + operations: $ReadOnlyArray, + ) => Promise; +initializeCryptoAccount: () => Promise; +getUserPublicKey: () => Promise; +getOneTimeKeys: (oneTimeKeysAmount: number) => Promise;