diff --git a/native/cpp/CommonCpp/NativeModules/CommRustModule.h b/native/cpp/CommonCpp/NativeModules/CommRustModule.h --- a/native/cpp/CommonCpp/NativeModules/CommRustModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommRustModule.h @@ -49,6 +49,12 @@ jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String socialProof) override; + virtual jsi::Value updatePassword( + jsi::Runtime &rt, + jsi::String userID, + jsi::String deviceID, + jsi::String accessToken, + jsi::String password) override; public: CommRustModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker); diff --git a/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp b/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp @@ -173,4 +173,30 @@ }); } +jsi::Value CommRustModule::updatePassword( + jsi::Runtime &rt, + jsi::String userID, + jsi::String deviceID, + jsi::String accessToken, + jsi::String password) { + return createPromiseAsJSIValue( + rt, + [this, &userID, &deviceID, &accessToken, &password]( + jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) { + std::string error; + try { + auto currentID = RustPromiseManager::instance.addPromise( + promise, this->jsInvoker_, innerRt); + identityUpdateUserPassword( + jsiStringToRustString(userID, innerRt), + jsiStringToRustString(deviceID, innerRt), + jsiStringToRustString(accessToken, innerRt), + jsiStringToRustString(password, innerRt), + currentID); + } catch (const std::exception &e) { + error = e.what(); + }; + }); +} + } // namespace comm diff --git a/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp b/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp --- a/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp @@ -24,6 +24,9 @@ static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_loginWalletUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->loginWalletUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt), args[8].asObject(rt).asArray(rt), args[9].asObject(rt).asArray(rt), args[10].asString(rt)); } +static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_updatePassword(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->updatePassword(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt)); +} CommRustModuleSchemaCxxSpecJSI::CommRustModuleSchemaCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker) : TurboModule("CommRustTurboModule", jsInvoker) { @@ -31,6 +34,7 @@ methodMap_["registerUser"] = MethodMetadata {10, __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerUser}; methodMap_["loginPasswordUser"] = MethodMetadata {10, __hostFunction_CommRustModuleSchemaCxxSpecJSI_loginPasswordUser}; methodMap_["loginWalletUser"] = MethodMetadata {11, __hostFunction_CommRustModuleSchemaCxxSpecJSI_loginWalletUser}; + methodMap_["updatePassword"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_updatePassword}; } diff --git a/native/cpp/CommonCpp/_generated/rustJSI.h b/native/cpp/CommonCpp/_generated/rustJSI.h --- a/native/cpp/CommonCpp/_generated/rustJSI.h +++ b/native/cpp/CommonCpp/_generated/rustJSI.h @@ -24,6 +24,7 @@ virtual jsi::Value registerUser(jsi::Runtime &rt, jsi::String username, jsi::String password, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys) = 0; virtual jsi::Value loginPasswordUser(jsi::Runtime &rt, jsi::String username, jsi::String password, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys) = 0; virtual jsi::Value loginWalletUser(jsi::Runtime &rt, jsi::String siweMessage, jsi::String siweSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String socialProof) = 0; + virtual jsi::Value updatePassword(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String password) = 0; }; @@ -77,6 +78,14 @@ return bridging::callFromJs<jsi::Value>( rt, &T::loginWalletUser, jsInvoker_, instance_, std::move(siweMessage), std::move(siweSignature), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature), std::move(contentOneTimeKeys), std::move(notifOneTimeKeys), std::move(socialProof)); } + jsi::Value updatePassword(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String password) override { + static_assert( + bridging::getParameterCount(&T::updatePassword) == 5, + "Expected updatePassword(...) to have 5 parameters"); + + return bridging::callFromJs<jsi::Value>( + rt, &T::updatePassword, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(accessToken), std::move(password)); + } private: T *instance_; diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -1,4 +1,4 @@ -use crate::ffi::string_callback; +use crate::ffi::{string_callback, void_callback}; use crate::identity::Empty; use comm_opaque2::client::{Login, Registration}; use comm_opaque2::grpc::opaque_error_to_grpc_status as handle_error; @@ -23,7 +23,8 @@ use identity::{ DeviceKeyUpload, DeviceType, IdentityKeyInfo, OpaqueLoginFinishRequest, OpaqueLoginStartRequest, PreKey, RegistrationFinishRequest, - RegistrationStartRequest, WalletLoginRequest, + RegistrationStartRequest, UpdateUserPasswordFinishRequest, + UpdateUserPasswordStartRequest, WalletLoginRequest, }; #[cfg(not(feature = "android"))] @@ -104,6 +105,15 @@ promise_id: u32, ); + #[cxx_name = "identityUpdateUserPassword"] + fn update_user_password( + user_id: String, + device_id: String, + access_token: String, + password: String, + promise_id: u32, + ); + #[cxx_name = "identityGenerateNonce"] fn generate_nonce(promise_id: u32); @@ -119,6 +129,10 @@ #[namespace = "comm"] #[cxx_name = "stringCallback"] fn string_callback(error: String, promise_id: u32, ret: String); + + #[namespace = "comm"] + #[cxx_name = "voidCallback"] + fn void_callback(error: String, promise_id: u32); } } @@ -134,6 +148,16 @@ } } +fn handle_void_result_as_callback<E>(result: Result<(), E>, promise_id: u32) +where + E: std::fmt::Display, +{ + match result { + Err(e) => void_callback(e.to_string(), promise_id), + Ok(_) => void_callback("".to_string(), promise_id), + } +} + fn generate_nonce(promise_id: u32) { RUNTIME.spawn(async move { let result = fetch_nonce().await; @@ -453,6 +477,70 @@ Ok(serde_json::to_string(&user_id_and_access_token)?) } +struct UpdatePasswordInfo { + user_id: String, + device_id: String, + access_token: String, + password: String, +} + +fn update_user_password( + user_id: String, + device_id: String, + access_token: String, + password: String, + promise_id: u32, +) { + RUNTIME.spawn(async move { + let update_password_info = UpdatePasswordInfo { + access_token, + user_id, + device_id, + password, + }; + let result = update_user_password_helper(update_password_info).await; + handle_void_result_as_callback(result, promise_id); + }); +} + +async fn update_user_password_helper( + update_password_info: UpdatePasswordInfo, +) -> Result<(), Error> { + let mut client_registration = Registration::new(); + let opaque_registration_request = client_registration + .start(&update_password_info.password) + .map_err(handle_error)?; + let update_password_start_request = UpdateUserPasswordStartRequest { + opaque_registration_request, + access_token: update_password_info.access_token, + user_id: update_password_info.user_id, + device_id_key: update_password_info.device_id, + }; + let mut identity_client = + IdentityClientServiceClient::connect("http://127.0.0.1:50054").await?; + let update_password_start_respone = identity_client + .update_user_password_start(update_password_start_request) + .await? + .into_inner(); + + let opaque_registration_upload = client_registration + .finish( + &update_password_info.password, + &update_password_start_respone.opaque_registration_response, + ) + .map_err(handle_error)?; + let update_password_finish_request = UpdateUserPasswordFinishRequest { + session_id: update_password_start_respone.session_id, + opaque_registration_upload, + }; + + identity_client + .update_user_password_finish(update_password_finish_request) + .await?; + + Ok(()) +} + #[derive( Debug, derive_more::Display, derive_more::From, derive_more::Error, )] diff --git a/native/schema/CommRustModuleSchema.js b/native/schema/CommRustModuleSchema.js --- a/native/schema/CommRustModuleSchema.js +++ b/native/schema/CommRustModuleSchema.js @@ -44,6 +44,12 @@ notifOneTimeKeys: $ReadOnlyArray<string>, socialProof: string, ) => Promise<string>; + +updatePassword: ( + userID: string, + deviceID: string, + accessToken: string, + password: string, + ) => Promise<void>; } export default (TurboModuleRegistry.getEnforcing<Spec>(