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 @@ -17,6 +17,7 @@ "ThreadStoreOperations.h" "ReportStoreOperations.h" "DraftStoreOperations.h" + "UserStoreOperations.h" ) set(NATIVE_SRCS @@ -77,12 +78,14 @@ ${_data_stores_path}/ThreadStore.h ${_data_stores_path}/MessageStore.h ${_data_stores_path}/ReportStore.h + ${_data_stores_path}/UserStore.h ) set(DATA_STORES_SRCS ${_data_stores_path}/DraftStore.cpp ${_data_stores_path}/ThreadStore.cpp ${_data_stores_path}/MessageStore.cpp ${_data_stores_path}/ReportStore.cpp + ${_data_stores_path}/UserStore.cpp ) add_library(comm-modules-persistentstorage 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 @@ -8,6 +8,7 @@ #include "PersistentStorageUtilities/DataStores/MessageStore.h" #include "PersistentStorageUtilities/DataStores/ReportStore.h" #include "PersistentStorageUtilities/DataStores/ThreadStore.h" +#include "PersistentStorageUtilities/DataStores/userStore.h" #include #include #include @@ -29,6 +30,7 @@ ThreadStore threadStore; MessageStore messageStore; ReportStore reportStore; + UserStore userStore; virtual jsi::Value getDraft(jsi::Runtime &rt, jsi::String key) override; virtual jsi::Value @@ -59,6 +61,8 @@ virtual void processThreadStoreOperationsSync( jsi::Runtime &rt, jsi::Array operations) override; + virtual jsi::Value + processUserStoreOperations(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 @@ -274,6 +274,12 @@ this->reportStore.processStoreOperationsSync(rt, std::move(operations)); } +jsi::Value CommCoreModule::processUserStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) { + return this->userStore.processStoreOperations(rt, std::move(operations)); +} + void CommCoreModule::terminate(jsi::Runtime &rt) { TerminateApp::terminate(); } @@ -681,7 +687,8 @@ draftStore(jsInvoker), threadStore(jsInvoker), messageStore(jsInvoker), - reportStore(jsInvoker) { + reportStore(jsInvoker), + userStore(jsInvoker) { GlobalDBSingleton::instance.enableMultithreading(); } diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/UserStore.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/UserStore.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/UserStore.h @@ -0,0 +1,29 @@ +#pragma once + +#include "../../../DatabaseManagers/entities/UserInfo.h" +#include "BaseDataStore.h" +#include "UserStoreOperations.h" + +#include + +namespace comm { + +class UserStore : public BaseDataStore { +private: + static OperationType REMOVE_OPERATION; + static OperationType REMOVE_ALL_OPERATION; + static OperationType REPLACE_OPERATION; + +public: + UserStore(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/UserStore.cpp b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/UserStore.cpp new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/UserStore.cpp @@ -0,0 +1,62 @@ +#include "UserStore.h" + +#include +#include + +namespace comm { + +OperationType UserStore::REMOVE_OPERATION = "remove_users"; +OperationType UserStore::REMOVE_ALL_OPERATION = "remove_all_users"; +OperationType UserStore::REPLACE_OPERATION = "replace_user"; + +UserStore::UserStore(std::shared_ptr jsInvoker) + : BaseDataStore(jsInvoker) { +} + +jsi::Array UserStore::parseDBDataStore( + jsi::Runtime &rt, + std::shared_ptr> usersVectorPtr) const { + jsi::Array jsiUsers = jsi::Array(rt, 0); + return jsiUsers; +} + +std::vector> +UserStore::createOperations(jsi::Runtime &rt, const jsi::Array &operations) + const { + std::vector> userStoreOps; + + 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 userIDsToRemove; + jsi::Object payloadObj = op.getProperty(rt, "payload").asObject(rt); + jsi::Array userIDs = + payloadObj.getProperty(rt, "ids").asObject(rt).asArray(rt); + for (int userIdx = 0; userIdx < userIDs.size(rt); userIdx++) { + userIDsToRemove.push_back( + userIDs.getValueAtIndex(rt, userIdx).asString(rt).utf8(rt)); + } + userStoreOps.push_back( + std::make_unique(std::move(userIDsToRemove))); + } else if (opType == REMOVE_ALL_OPERATION) { + userStoreOps.push_back(std::make_unique()); + } else if (opType == REPLACE_OPERATION) { + jsi::Object userObj = op.getProperty(rt, "payload").asObject(rt); + std::string id = userObj.getProperty(rt, "id").asString(rt).utf8(rt); + std::string user_info = + userObj.getProperty(rt, "userInfo").asString(rt).utf8(rt); + + UserInfo user{id, user_info}; + + userStoreOps.push_back( + std::make_unique(std::move(user))); + } else { + throw std::runtime_error("unsupported operation: " + opType); + } + }; + return userStoreOps; +} + +} // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/UserStoreOperations.h b/native/cpp/CommonCpp/NativeModules/UserStoreOperations.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/UserStoreOperations.h @@ -0,0 +1,47 @@ +#pragma once + +#include "../DatabaseManagers/entities/UserInfo.h" +#include "DatabaseManager.h" +#include + +namespace comm { +class UserStoreOperationBase { +public: + virtual void execute() = 0; + virtual ~UserStoreOperationBase(){}; +}; + +class RemoveUsersOperation : public UserStoreOperationBase { +public: + RemoveUsersOperation(std::vector ids) : ids{ids} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeUsers(this->ids); + } + +private: + std::vector ids; +}; + +class ReplaceUserOperation : public UserStoreOperationBase { +public: + ReplaceUserOperation(UserInfo &&user) : user{std::move(user)} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().replaceUser(this->user); + } + +private: + UserInfo user; +}; + +class RemoveAllUsersOperation : public UserStoreOperationBase { +public: + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeAllUsers(); + } +}; + +} // 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 @@ -57,6 +57,9 @@ static_cast(&turboModule)->processThreadStoreOperationsSync(rt, args[0].asObject(rt).asArray(rt)); return jsi::Value::undefined(); } +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_initializeCryptoAccount(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->initializeCryptoAccount(rt); } @@ -142,6 +145,7 @@ methodMap_["processReportStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processReportStoreOperations}; methodMap_["processReportStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processReportStoreOperationsSync}; methodMap_["processThreadStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperationsSync}; + methodMap_["processUserStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processUserStoreOperations}; 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 @@ -34,6 +34,7 @@ virtual jsi::Value processReportStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; 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 initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; virtual jsi::Value getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; @@ -189,6 +190,14 @@ return bridging::callFromJs( rt, &T::processThreadStoreOperationsSync, jsInvoker_, instance_, std::move(operations)); } + jsi::Value processUserStoreOperations(jsi::Runtime &rt, jsi::Array operations) override { + static_assert( + bridging::getParameterCount(&T::processUserStoreOperations) == 2, + "Expected processUserStoreOperations(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::processUserStoreOperations, 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 */; }; + 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 */; }; 8EA59BD62A6E8E0400EB4F53 /* DraftStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EA59BD42A6E8E0400EB4F53 /* DraftStore.cpp */; }; @@ -197,6 +198,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 = ""; }; + 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 = ""; }; 8E43C32B291E5B4A009378F5 /* TerminateApp.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TerminateApp.mm; path = Comm/TerminateApp.mm; sourceTree = ""; }; 8E43C32E291E5B9D009378F5 /* TerminateApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TerminateApp.h; path = ../cpp/CommonCpp/Tools/TerminateApp.h; sourceTree = ""; }; 8E86A6D229537EBB000BBE7D /* DatabaseManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseManager.cpp; sourceTree = ""; }; @@ -413,6 +417,7 @@ 71BE843A2636A944002849D2 /* NativeModules */ = { isa = PBXGroup; children = ( + 8E3994562B039A9300D5E950 /* UserStoreOperations.h */, 8EA59BD22A6E800100EB4F53 /* NativeModuleUtils.h */, 8EF775672A74032C0046A385 /* CommRustModule.cpp */, 8EF775662A74032C0046A385 /* CommRustModule.h */, @@ -587,6 +592,8 @@ 8EA59BD02A6E786200EB4F53 /* DataStores */ = { isa = PBXGroup; children = ( + 8E3994532B039A7C00D5E950 /* UserStore.cpp */, + 8E3994542B039A7C00D5E950 /* UserStore.h */, 8EF7756F2A751B780046A385 /* ReportStore.cpp */, 8EF775702A751B780046A385 /* ReportStore.h */, 8EF7756D2A7513F40046A385 /* MessageStore.cpp */, @@ -1065,6 +1072,7 @@ CB38B48628771CDD00171182 /* TemporaryMessageStorage.mm in Sources */, CB38B48428771CAF00171182 /* EncryptedFileUtils.mm in Sources */, CBFE58292885852B003B94C9 /* ThreadOperations.cpp in Sources */, + 8E3994552B039A7C00D5E950 /* UserStore.cpp in Sources */, 7FBB2A7829E945C2002C6493 /* CommUtilsModule.cpp in Sources */, CB38B48228771C7A00171182 /* NonBlockingLock.mm in Sources */, 718DE99E2653D41C00365824 /* WorkerThread.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 @@ -8,6 +8,7 @@ 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'; +import type { ClientDBUserStoreOperation } from 'lib/ops/user-store-ops'; import type { OLMOneTimeKeys } from 'lib/types/crypto-types'; import type { ClientDBDraftStoreOperation } from 'lib/types/draft-types.js'; import type { ClientDBMessageInfo } from 'lib/types/message-types.js'; @@ -69,6 +70,9 @@ +processThreadStoreOperationsSync: ( operations: $ReadOnlyArray, ) => void; + +processUserStoreOperations: ( + operations: $ReadOnlyArray, + ) => Promise; +initializeCryptoAccount: () => Promise; +getUserPublicKey: () => Promise; +getPrimaryOneTimeKeys: (