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 @@ -20,6 +20,7 @@ "UserStoreOperations.h" "KeyserverStoreOperations.h" "CommunityStoreOperations.h" + "IntegrityStoreOperations.h" ) set(NATIVE_SRCS @@ -83,6 +84,7 @@ ${_data_stores_path}/UserStore.h ${_data_stores_path}/KeyserverStore.h ${_data_stores_path}/CommunityStore.h + ${_data_stores_path}/IntegrityStore.h ) set(DATA_STORES_SRCS ${_data_stores_path}/DraftStore.cpp @@ -92,6 +94,7 @@ ${_data_stores_path}/UserStore.cpp ${_data_stores_path}/KeyserverStore.cpp ${_data_stores_path}/CommunityStore.cpp + ${_data_stores_path}/IntegrityStore.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 @@ -6,6 +6,7 @@ #include "../_generated/commJSI.h" #include "PersistentStorageUtilities/DataStores/CommunityStore.h" #include "PersistentStorageUtilities/DataStores/DraftStore.h" +#include "PersistentStorageUtilities/DataStores/IntegrityStore.h" #include "PersistentStorageUtilities/DataStores/KeyserverStore.h" #include "PersistentStorageUtilities/DataStores/MessageStore.h" #include "PersistentStorageUtilities/DataStores/ReportStore.h" @@ -34,6 +35,7 @@ UserStore userStore; KeyserverStore keyserverStore; CommunityStore communityStore; + IntegrityStore integrityStore; void persistCryptoModule(); @@ -74,6 +76,9 @@ virtual jsi::Value processCommunityStoreOperations( jsi::Runtime &rt, jsi::Array operations) override; + virtual jsi::Value processIntegrityStoreOperations( + 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 @@ -329,6 +329,12 @@ return this->communityStore.processStoreOperations(rt, std::move(operations)); } +jsi::Value CommCoreModule::processIntegrityStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) { + return this->integrityStore.processStoreOperations(rt, std::move(operations)); +} + void CommCoreModule::terminate(jsi::Runtime &rt) { TerminateApp::terminate(); } @@ -1070,7 +1076,8 @@ reportStore(jsInvoker), userStore(jsInvoker), keyserverStore(jsInvoker), - communityStore(jsInvoker) { + communityStore(jsInvoker), + integrityStore(jsInvoker) { GlobalDBSingleton::instance.enableMultithreading(); } diff --git a/native/cpp/CommonCpp/NativeModules/IntegrityStoreOperations.h b/native/cpp/CommonCpp/NativeModules/IntegrityStoreOperations.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/IntegrityStoreOperations.h @@ -0,0 +1,54 @@ +#pragma once + +#include "../DatabaseManagers/entities/IntegrityThreadHash.h" +#include "DatabaseManager.h" +#include + +namespace comm { +class IntegrityStoreOperationBase { +public: + virtual void execute() = 0; + virtual ~IntegrityStoreOperationBase(){}; +}; + +class RemoveIntegrityThreadHashesOperation + : public IntegrityStoreOperationBase { +public: + RemoveIntegrityThreadHashesOperation(std::vector ids) + : ids{ids} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeIntegrityThreadHashes(this->ids); + } + +private: + std::vector ids; +}; + +class ReplaceIntegrityThreadHashesOperation + : public IntegrityStoreOperationBase { +public: + ReplaceIntegrityThreadHashesOperation( + std::vector &&threadHashes) + : threadHashes{std::move(threadHashes)} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().replaceIntegrityThreadHashes( + this->threadHashes); + } + +private: + std::vector threadHashes; +}; + +class RemoveAllIntegrityThreadHashesOperation + : public IntegrityStoreOperationBase { +public: + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeAllIntegrityThreadHashes(); + } +}; + +} // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/IntegrityStore.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/IntegrityStore.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/IntegrityStore.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../../../DatabaseManagers/entities/IntegrityThreadHash.h" +#include "BaseDataStore.h" +#include "IntegrityStoreOperations.h" + +#include + +namespace comm { + +class IntegrityStore + : public BaseDataStore { +private: + static OperationType REMOVE_OPERATION; + static OperationType REMOVE_ALL_OPERATION; + static OperationType REPLACE_OPERATION; + +public: + IntegrityStore(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/IntegrityStore.cpp b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/IntegrityStore.cpp new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/IntegrityStore.cpp @@ -0,0 +1,89 @@ +#include "IntegrityStore.h" +#include "IntegrityThreadHash.h" + +#include +#include + +namespace comm { + +OperationType IntegrityStore::REMOVE_OPERATION = + "remove_integrity_thread_hashes"; +OperationType IntegrityStore::REMOVE_ALL_OPERATION = + "remove_all_integrity_thread_hashes"; +OperationType IntegrityStore::REPLACE_OPERATION = + "replace_integrity_thread_hashes"; + +IntegrityStore::IntegrityStore( + std::shared_ptr jsInvoker) + : BaseDataStore(jsInvoker) { +} + +jsi::Array IntegrityStore::parseDBDataStore( + jsi::Runtime &rt, + std::shared_ptr> + integrityThreadHashesVectorPtr) const { + jsi::Array jsiIntegrityThreadHashes = jsi::Array(rt, 0); + return jsiIntegrityThreadHashes; +} + +std::vector> +IntegrityStore::createOperations(jsi::Runtime &rt, const jsi::Array &operations) + const { + std::vector> integrityStoreOps; + + 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 integrityThreadHashIDsToRemove; + jsi::Object payloadObj = op.getProperty(rt, "payload").asObject(rt); + jsi::Array integrityThreadHashIDs = + payloadObj.getProperty(rt, "ids").asObject(rt).asArray(rt); + for (int integrityThreadHashIDIdx = 0; + integrityThreadHashIDIdx < integrityThreadHashIDs.size(rt); + integrityThreadHashIDIdx++) { + integrityThreadHashIDsToRemove.push_back( + integrityThreadHashIDs.getValueAtIndex(rt, integrityThreadHashIDIdx) + .asString(rt) + .utf8(rt)); + } + integrityStoreOps.push_back( + std::make_unique( + std::move(integrityThreadHashIDsToRemove))); + } else if (opType == REMOVE_ALL_OPERATION) { + integrityStoreOps.push_back( + std::make_unique()); + } else if (opType == REPLACE_OPERATION) { + std::vector integrityThreadHashesToReplace; + jsi::Object payloadObj = op.getProperty(rt, "payload").asObject(rt); + jsi::Array integrityThreadHashes = + payloadObj.getProperty(rt, "threadHashes").asObject(rt).asArray(rt); + + for (int integrityThreadHashIdx = 0; + integrityThreadHashIdx < integrityThreadHashes.size(rt); + integrityThreadHashIdx++) { + jsi::Object integrityThreadHashObj = + integrityThreadHashes.getValueAtIndex(rt, integrityThreadHashIdx) + .asObject(rt); + + std::string id = + integrityThreadHashObj.getProperty(rt, "id").asString(rt).utf8(rt); + int threadHash = + integrityThreadHashObj.getProperty(rt, "threadHash").asNumber(); + + IntegrityThreadHash integrityThreadHash{id, threadHash}; + + integrityThreadHashesToReplace.push_back(integrityThreadHash); + } + integrityStoreOps.push_back( + std::make_unique( + std::move(integrityThreadHashesToReplace))); + } else { + throw std::runtime_error("unsupported operation: " + opType); + } + }; + return integrityStoreOps; +} + +} // namespace comm \ No newline at end of file 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 @@ -66,6 +66,9 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processCommunityStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->processCommunityStoreOperations(rt, args[0].asObject(rt).asArray(rt)); } +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processIntegrityStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->processIntegrityStoreOperations(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); } @@ -183,6 +186,7 @@ methodMap_["processUserStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processUserStoreOperations}; methodMap_["processKeyserverStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processKeyserverStoreOperations}; methodMap_["processCommunityStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processCommunityStoreOperations}; + methodMap_["processIntegrityStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processIntegrityStoreOperations}; 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 @@ -37,6 +37,7 @@ virtual jsi::Value processUserStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value processKeyserverStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; 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 initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; virtual jsi::Value getOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; @@ -225,6 +226,14 @@ return bridging::callFromJs( rt, &T::processCommunityStoreOperations, jsInvoker_, instance_, std::move(operations)); } + jsi::Value processIntegrityStoreOperations(jsi::Runtime &rt, jsi::Array operations) override { + static_assert( + bridging::getParameterCount(&T::processIntegrityStoreOperations) == 2, + "Expected processIntegrityStoreOperations(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::processIntegrityStoreOperations, 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 @@ -11,6 +11,7 @@ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 1F537ACC7B60DC049C0ECFA7 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 769A87FB41BCE3FEF97FD59A /* ExpoModulesProvider.swift */; }; + 34329B442B9EC7EC00233438 /* IntegrityStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34329B3F2B9EBFCE00233438 /* IntegrityStore.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 */; }; @@ -137,6 +138,9 @@ 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Comm/main.m; sourceTree = ""; }; 2DDA0A22FECC9DAA5C19C35D /* Metadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metadata.h; sourceTree = ""; }; 34329B452B9EC96200233438 /* IntegrityThreadHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntegrityThreadHash.h; sourceTree = ""; }; + 34329B3E2B9EBD3400233438 /* IntegrityStoreOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntegrityStoreOperations.h; sourceTree = ""; }; + 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 = ""; }; 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 = ""; }; @@ -459,6 +463,7 @@ isa = PBXGroup; children = ( B3B02EBE2B8538860020D118 /* CommunityStoreOperations.h */, + 34329B3E2B9EBD3400233438 /* IntegrityStoreOperations.h */, 8E2CC2562B5C999A000C94D6 /* KeyserverStoreOperations.h */, CBA784382B28AC4300E9F419 /* CommServicesAuthMetadataEmitter.h */, 8E3994562B039A9300D5E950 /* UserStoreOperations.h */, @@ -640,6 +645,8 @@ 8E2CC2572B5C99B0000C94D6 /* KeyserverStore.h */, B3B02EBD2B8536560020D118 /* CommunityStore.cpp */, B3B02EBC2B8534C00020D118 /* CommunityStore.h */, + 34329B3F2B9EBFCE00233438 /* IntegrityStore.cpp */, + 34329B402B9EBFCE00233438 /* IntegrityStore.h */, 8E3994532B039A7C00D5E950 /* UserStore.cpp */, 8E3994542B039A7C00D5E950 /* UserStore.h */, 8EF7756F2A751B780046A385 /* ReportStore.cpp */, @@ -1158,6 +1165,7 @@ CB38F2B1286C6C870010535C /* MessageOperationsUtilities.cpp in Sources */, DFD5E7862B052B1400C32B6A /* RustAESCrypto.cpp in Sources */, 8EF775712A751B780046A385 /* ReportStore.cpp in Sources */, + 34329B442B9EC7EC00233438 /* IntegrityStore.cpp in Sources */, 71CA4A64262DA8E500835C89 /* Logger.mm in Sources */, 71BF5B7F26BBDD7400EDE27D /* CryptoModule.cpp in Sources */, CB24361829A39A2500FEC4E1 /* NotificationsCryptoModule.cpp in Sources */, diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -6,6 +6,7 @@ import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport.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'; import type { ClientDBMessageStoreOperation } from 'lib/ops/message-store-ops.js'; import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js'; @@ -74,6 +75,9 @@ +processCommunityStoreOperations: ( operations: $ReadOnlyArray, ) => Promise; + +processIntegrityStoreOperations: ( + operations: $ReadOnlyArray, + ) => Promise; +initializeCryptoAccount: () => Promise; +getUserPublicKey: () => Promise; +getOneTimeKeys: (oneTimeKeysAmount: number) => Promise;