diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp @@ -1337,9 +1337,10 @@ SQLiteQueryExecutor::getStorage().remove_all(); } -void SQLiteQueryExecutor::removeKeyservers(const std::vector &ids) const { +void SQLiteQueryExecutor::removeKeyservers( + const std::vector &ids) const { SQLiteQueryExecutor::getStorage().remove_all( - where(in(&KeyserverInfo::id, ids))); + where(in(&KeyserverInfo::id, ids))); } std::vector SQLiteQueryExecutor::getAllKeyservers() const { 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 @@ -18,6 +18,7 @@ "ReportStoreOperations.h" "DraftStoreOperations.h" "UserStoreOperations.h" + "KeyserverStoreOperations.h" ) set(NATIVE_SRCS @@ -79,6 +80,7 @@ ${_data_stores_path}/MessageStore.h ${_data_stores_path}/ReportStore.h ${_data_stores_path}/UserStore.h + ${_data_stores_path}/KeyserverStore.h ) set(DATA_STORES_SRCS ${_data_stores_path}/DraftStore.cpp @@ -86,6 +88,7 @@ ${_data_stores_path}/MessageStore.cpp ${_data_stores_path}/ReportStore.cpp ${_data_stores_path}/UserStore.cpp + ${_data_stores_path}/KeyserverStore.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/WorkerThread.h" #include "../_generated/commJSI.h" #include "PersistentStorageUtilities/DataStores/DraftStore.h" +#include "PersistentStorageUtilities/DataStores/KeyserverStore.h" #include "PersistentStorageUtilities/DataStores/MessageStore.h" #include "PersistentStorageUtilities/DataStores/ReportStore.h" #include "PersistentStorageUtilities/DataStores/ThreadStore.h" @@ -30,6 +31,7 @@ MessageStore messageStore; ReportStore reportStore; UserStore userStore; + KeyserverStore keyserverStore; void persistCryptoModule(); @@ -64,6 +66,9 @@ jsi::Array operations) override; virtual jsi::Value processUserStoreOperations(jsi::Runtime &rt, jsi::Array operations) override; + virtual jsi::Value processKeyserverStoreOperations( + 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 @@ -291,6 +291,12 @@ return this->userStore.processStoreOperations(rt, std::move(operations)); } +jsi::Value CommCoreModule::processKeyserverStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) { + return this->keyserverStore.processStoreOperations(rt, std::move(operations)); +} + void CommCoreModule::terminate(jsi::Runtime &rt) { TerminateApp::terminate(); } @@ -982,7 +988,8 @@ threadStore(jsInvoker), messageStore(jsInvoker), reportStore(jsInvoker), - userStore(jsInvoker) { + userStore(jsInvoker), + keyserverStore(jsInvoker) { GlobalDBSingleton::instance.enableMultithreading(); } diff --git a/native/cpp/CommonCpp/NativeModules/KeyserverStoreOperations.h b/native/cpp/CommonCpp/NativeModules/KeyserverStoreOperations.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/KeyserverStoreOperations.h @@ -0,0 +1,48 @@ +#pragma once + +#include "../DatabaseManagers/entities/KeyserverInfo.h" +#include "DatabaseManager.h" +#include + +namespace comm { +class KeyserverStoreOperationBase { +public: + virtual void execute() = 0; + virtual ~KeyserverStoreOperationBase(){}; +}; + +class RemoveKeyserversOperation : public KeyserverStoreOperationBase { +public: + RemoveKeyserversOperation(std::vector ids) : ids{ids} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeKeyservers(this->ids); + } + +private: + std::vector ids; +}; + +class ReplaceKeyserverOperation : public KeyserverStoreOperationBase { +public: + ReplaceKeyserverOperation(KeyserverInfo &&keyserver) + : keyserver{std::move(keyserver)} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().replaceKeyserver(this->keyserver); + } + +private: + KeyserverInfo keyserver; +}; + +class RemoveAllKeyserversOperation : public KeyserverStoreOperationBase { +public: + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeAllKeyservers(); + } +}; + +} // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/KeyserverStore.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/KeyserverStore.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/KeyserverStore.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../../../DatabaseManagers/entities/KeyserverInfo.h" +#include "BaseDataStore.h" +#include "KeyserverStoreOperations.h" + +#include + +namespace comm { + +class KeyserverStore + : public BaseDataStore { +private: + static OperationType REMOVE_OPERATION; + static OperationType REMOVE_ALL_OPERATION; + static OperationType REPLACE_OPERATION; + +public: + KeyserverStore(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/KeyserverStore.cpp b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/KeyserverStore.cpp new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/KeyserverStore.cpp @@ -0,0 +1,67 @@ +#include "KeyserverStore.h" + +#include +#include + +namespace comm { + +OperationType KeyserverStore::REMOVE_OPERATION = "remove_keyservers"; +OperationType KeyserverStore::REMOVE_ALL_OPERATION = "remove_all_keyservers"; +OperationType KeyserverStore::REPLACE_OPERATION = "replace_keyserver"; + +KeyserverStore::KeyserverStore( + std::shared_ptr jsInvoker) + : BaseDataStore(jsInvoker) { +} + +jsi::Array KeyserverStore::parseDBDataStore( + jsi::Runtime &rt, + std::shared_ptr> keyserversVectorPtr) const { + jsi::Array jsiKeyservers = jsi::Array(rt, 0); + return jsiKeyservers; +} + +std::vector> +KeyserverStore::createOperations(jsi::Runtime &rt, const jsi::Array &operations) + const { + std::vector> keyserverStoreOps; + + 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 keyserverIDsToRemove; + jsi::Object payloadObj = op.getProperty(rt, "payload").asObject(rt); + jsi::Array keyserverIDs = + payloadObj.getProperty(rt, "ids").asObject(rt).asArray(rt); + for (int keyserverIdx = 0; keyserverIdx < keyserverIDs.size(rt); + keyserverIdx++) { + keyserverIDsToRemove.push_back( + keyserverIDs.getValueAtIndex(rt, keyserverIdx) + .asString(rt) + .utf8(rt)); + } + keyserverStoreOps.push_back(std::make_unique( + std::move(keyserverIDsToRemove))); + } else if (opType == REMOVE_ALL_OPERATION) { + keyserverStoreOps.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 keyserver_info = + payloadObj.getProperty(rt, "keyserverInfo").asString(rt).utf8(rt); + + KeyserverInfo keyserver{id, keyserver_info}; + + keyserverStoreOps.push_back( + std::make_unique(std::move(keyserver))); + } else { + throw std::runtime_error("unsupported operation: " + opType); + } + }; + return keyserverStoreOps; +} + +} // 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 @@ -60,6 +60,9 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processUserStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->processUserStoreOperations(rt, args[0].asObject(rt).asArray(rt)); } +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processKeyserverStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->processKeyserverStoreOperations(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); } @@ -175,6 +178,7 @@ methodMap_["processReportStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processReportStoreOperationsSync}; methodMap_["processThreadStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperationsSync}; methodMap_["processUserStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processUserStoreOperations}; + methodMap_["processKeyserverStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processKeyserverStoreOperations}; methodMap_["initializeCryptoAccount"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount}; methodMap_["getUserPublicKey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserPublicKey}; methodMap_["getPrimaryOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getPrimaryOneTimeKeys}; 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 @@ -35,6 +35,7 @@ virtual void processReportStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) = 0; virtual void processThreadStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) = 0; 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 initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; virtual jsi::Value getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; @@ -207,6 +208,14 @@ return bridging::callFromJs( rt, &T::processUserStoreOperations, jsInvoker_, instance_, std::move(operations)); } + jsi::Value processKeyserverStoreOperations(jsi::Runtime &rt, jsi::Array operations) override { + static_assert( + bridging::getParameterCount(&T::processKeyserverStoreOperations) == 2, + "Expected processKeyserverStoreOperations(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::processKeyserverStoreOperations, 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 @@ -45,6 +45,7 @@ 8B99BAAC28D50F3000EB5ADB /* libnative_rust_library.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B99BAAB28D50F3000EB5ADB /* libnative_rust_library.a */; }; 8B99BAAE28D511FF00EB5ADB /* lib.rs.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B99BAAD28D511FF00EB5ADB /* lib.rs.cc */; }; 8BC9568529FC49B00060AE4A /* JSIRust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8BC9568429FC49B00060AE4A /* JSIRust.cpp */; }; + 8E2CC2592B5C99B0000C94D6 /* KeyserverStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E2CC2582B5C99B0000C94D6 /* KeyserverStore.cpp */; }; 8E3994552B039A7C00D5E950 /* UserStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E3994532B039A7C00D5E950 /* UserStore.cpp */; }; 8E43C32C291E5B4A009378F5 /* TerminateApp.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8E43C32B291E5B4A009378F5 /* TerminateApp.mm */; }; 8E86A6D329537EBB000BBE7D /* DatabaseManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E86A6D229537EBB000BBE7D /* DatabaseManager.cpp */; }; @@ -204,6 +205,9 @@ 8B99BAAD28D511FF00EB5ADB /* lib.rs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lib.rs.cc; sourceTree = ""; }; 8BC9568329FC49920060AE4A /* JSIRust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSIRust.h; sourceTree = ""; }; 8BC9568429FC49B00060AE4A /* JSIRust.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIRust.cpp; sourceTree = ""; }; + 8E2CC2562B5C999A000C94D6 /* KeyserverStoreOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyserverStoreOperations.h; sourceTree = ""; }; + 8E2CC2572B5C99B0000C94D6 /* KeyserverStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeyserverStore.h; path = PersistentStorageUtilities/DataStores/KeyserverStore.h; sourceTree = ""; }; + 8E2CC2582B5C99B0000C94D6 /* KeyserverStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyserverStore.cpp; path = PersistentStorageUtilities/DataStores/KeyserverStore.cpp; sourceTree = ""; }; 8E3994532B039A7C00D5E950 /* UserStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserStore.cpp; path = PersistentStorageUtilities/DataStores/UserStore.cpp; sourceTree = ""; }; 8E3994542B039A7C00D5E950 /* UserStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserStore.h; path = PersistentStorageUtilities/DataStores/UserStore.h; sourceTree = ""; }; 8E3994562B039A9300D5E950 /* UserStoreOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserStoreOperations.h; sourceTree = ""; }; @@ -438,6 +442,7 @@ 71BE843A2636A944002849D2 /* NativeModules */ = { isa = PBXGroup; children = ( + 8E2CC2562B5C999A000C94D6 /* KeyserverStoreOperations.h */, CBA784382B28AC4300E9F419 /* CommServicesAuthMetadataEmitter.h */, 8E3994562B039A9300D5E950 /* UserStoreOperations.h */, 8EA59BD22A6E800100EB4F53 /* NativeModuleUtils.h */, @@ -620,6 +625,8 @@ 8EA59BD02A6E786200EB4F53 /* DataStores */ = { isa = PBXGroup; children = ( + 8E2CC2582B5C99B0000C94D6 /* KeyserverStore.cpp */, + 8E2CC2572B5C99B0000C94D6 /* KeyserverStore.h */, 8E3994532B039A7C00D5E950 /* UserStore.cpp */, 8E3994542B039A7C00D5E950 /* UserStore.h */, 8EF7756F2A751B780046A385 /* ReportStore.cpp */, @@ -1122,6 +1129,7 @@ 71762A75270D8AAE00F565ED /* PlatformSpecificTools.mm in Sources */, 71BF5B7126B3FF0900EDE27D /* Session.cpp in Sources */, 8EF7756E2A7513F40046A385 /* MessageStore.cpp in Sources */, + 8E2CC2592B5C99B0000C94D6 /* KeyserverStore.cpp in Sources */, DFD5E77C2B05181400C32B6A /* RustSecureStore.cpp in Sources */, 71BF5B7526B401D300EDE27D /* Tools.cpp in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.mm 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 { 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'; import type { ClientDBThreadStoreOperation } from 'lib/ops/thread-store-ops.js'; @@ -73,6 +74,9 @@ +processUserStoreOperations: ( operations: $ReadOnlyArray, ) => Promise; + +processKeyserverStoreOperations: ( + operations: $ReadOnlyArray, + ) => Promise; +initializeCryptoAccount: () => Promise; +getUserPublicKey: () => Promise; +getPrimaryOneTimeKeys: (