From 60beabeb1c9fb9be9866fe99d1309824c43dd75d Mon Sep 17 00:00:00 2001 From: danvleju-rdx <163979791+danvleju-rdx@users.noreply.github.com> Date: Fri, 29 Nov 2024 15:46:04 +0200 Subject: [PATCH] Factor Source name updates (#283) * rename Passphrase to Password + hint * wip * wip * wip * DRY factor source * wip * wip * bump version * wip * fmt * fixes + tests * bump version + fmt * fix test --------- Co-authored-by: Alexander Cyon --- Cargo.lock | 4 +- ...culusCardFactorSource+Wrap+Functions.swift | 4 +- .../Factor/FactorSource+Wrap+Functions.swift | 4 + .../PassphraseFactorSource+Functions.swift | 10 -- .../PasswordFactorSource+Functions.swift | 14 ++ .../BIP39/Mnemonic+SampleValues.swift | 8 +- .../PassphraseFactorSource+SampleValues.swift | 11 -- .../PasswordFactorSource+SampleValues.swift | 11 ++ .../FactorSource+Swiftified.swift | 12 +- ... => PasswordFactorSource+Swiftified.swift} | 20 +-- .../Factor/ArculusCardFactorSourceTests.swift | 2 +- .../Profile/Factor/FactorSourceTests.swift | 4 + ...edgerHardwareWalletFactorSourceTests.swift | 2 +- .../OffDeviceMnemonicFactorSourceTests.swift | 2 +- ....swift => PasswordFactorSourceTests.swift} | 15 +- crates/sargon-uniffi/Cargo.toml | 2 +- .../src/core/error/common_error.rs | 4 +- .../bip39/mnemonic.rs | 8 +- .../arculus_card_hint.rs | 5 +- .../src/profile/mfa/mfa_factor_sources/mod.rs | 2 + .../off_device_factor_source_hint.rs | 4 +- .../password_factor_source/mod.rs | 5 + .../password_factor_source.rs | 42 ++++++ .../password_factor_source_hint.rs | 9 ++ crates/sargon-uniffi/src/profile/mfa/mod.rs | 2 - .../mfa/passphrase_factor_source/mod.rs | 3 - .../passphrase_factor_source.rs | 38 ----- .../src/profile/v100/factors/factor_source.rs | 10 +- .../v100/factors/factor_source_kind.rs | 2 +- .../device_factor_source_hint.rs | 12 +- .../ledger_hardware_wallet_hint.rs | 7 +- crates/sargon/Cargo.toml | 2 +- crates/sargon/src/core/error/common_error.rs | 4 +- .../factor_instances_cache.rs | 2 +- .../factor_instances_provider_unit_tests.rs | 34 ++--- .../bip39/mnemonic.rs | 4 +- .../derivation/mnemonic_with_passphrase.rs | 8 +- .../arculus_card_factor_source.rs | 13 +- .../arculus_card_hint.rs | 13 +- .../src/profile/mfa/mfa_factor_sources/mod.rs | 4 +- .../off_device_factor_source_hint.rs | 8 +- .../off_device_mnemonic_factor_source.rs | 11 +- .../passphrase_factor_source/mod.rs | 3 - .../password_factor_source/mod.rs | 5 + .../password_factor_source.rs} | 82 ++++++---- .../password_factor_source_hint.rs | 56 +++++++ .../security_questions_factor_source.rs | 19 ++- .../trusted_contact_factor_source.rs | 11 +- .../src/profile/v100/factors/factor_source.rs | 142 ++++++++---------- .../factors/factor_source_id_from_hash.rs | 14 +- .../v100/factors/factor_source_kind.rs | 15 +- .../device_factor_source.rs | 11 +- .../device_factor_source_hint.rs | 41 ++++- .../ledger_hardware_wallet_factor_source.rs | 11 +- .../ledger_hardware_wallet_hint.rs | 16 +- .../profile/v100/factors/is_factor_source.rs | 20 ++- .../signing/collector/signatures_collector.rs | 8 +- .../src/system/sargon_os/sargon_os_factors.rs | 6 +- .../samples/factor_source_ids_with_samples.rs | 12 +- .../types/samples/factor_source_samples.rs | 11 +- .../Dependencies/FactorSourcesClient.swift | 6 +- .../sargon/extensions/FactorSource.kt | 14 +- .../com/radixdlt/sargon/FactorSourceTest.kt | 13 +- 63 files changed, 570 insertions(+), 327 deletions(-) delete mode 100644 apple/Sources/Sargon/Extensions/Methods/Profile/Factor/PassphraseFactorSource+Functions.swift create mode 100644 apple/Sources/Sargon/Extensions/Methods/Profile/Factor/PasswordFactorSource+Functions.swift delete mode 100644 apple/Sources/Sargon/Extensions/SampleValues/Profile/Factor/FactorSource/PassphraseFactorSource+SampleValues.swift create mode 100644 apple/Sources/Sargon/Extensions/SampleValues/Profile/Factor/FactorSource/PasswordFactorSource+SampleValues.swift rename apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/{PassphraseFactorSource+Swiftified.swift => PasswordFactorSource+Swiftified.swift} (50%) rename apple/Tests/TestCases/Profile/Factor/{PassphraseFactorSourceTests.swift => PasswordFactorSourceTests.swift} (76%) create mode 100644 crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/mod.rs create mode 100644 crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source.rs create mode 100644 crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source_hint.rs delete mode 100644 crates/sargon-uniffi/src/profile/mfa/passphrase_factor_source/mod.rs delete mode 100644 crates/sargon-uniffi/src/profile/mfa/passphrase_factor_source/passphrase_factor_source.rs delete mode 100644 crates/sargon/src/profile/mfa/mfa_factor_sources/passphrase_factor_source/mod.rs create mode 100644 crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/mod.rs rename crates/sargon/src/profile/mfa/mfa_factor_sources/{passphrase_factor_source/passphrase_factor_source.rs => password_factor_source/password_factor_source.rs} (61%) create mode 100644 crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source_hint.rs diff --git a/Cargo.lock b/Cargo.lock index ff0f3213b..57b109686 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2759,7 +2759,7 @@ dependencies = [ [[package]] name = "sargon" -version = "1.1.69" +version = "1.1.70" dependencies = [ "actix-rt", "aes-gcm", @@ -2814,7 +2814,7 @@ dependencies = [ [[package]] name = "sargon-uniffi" -version = "1.1.69" +version = "1.1.70" dependencies = [ "actix-rt", "assert-json-diff", diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/ArculusCardFactorSource+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/ArculusCardFactorSource+Wrap+Functions.swift index 02a223d62..58049cd66 100644 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/ArculusCardFactorSource+Wrap+Functions.swift +++ b/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/ArculusCardFactorSource+Wrap+Functions.swift @@ -14,8 +14,8 @@ extension ArculusCardFactorSource { public init( mnemonicWithPassphrase mwp: MnemonicWithPassphrase, - name: String + label: String ) { - self.init(mnemonicWithPassphrase: mwp, hint: .init(name: name, model: .arculusColdStorageWallet)) + self.init(mnemonicWithPassphrase: mwp, hint: .init(label: label, model: .arculusColdStorageWallet)) } } diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/FactorSource+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/FactorSource+Wrap+Functions.swift index 0490fa814..820adcc88 100644 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/FactorSource+Wrap+Functions.swift +++ b/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/FactorSource+Wrap+Functions.swift @@ -13,4 +13,8 @@ extension FactorSource { public var supportsBabylon: Bool { factorSourceSupportsBabylon(factorSource: self) } + + public var name: String { + factorSourceName(factorSource: self) + } } diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/PassphraseFactorSource+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/PassphraseFactorSource+Functions.swift deleted file mode 100644 index 1628c31bd..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/PassphraseFactorSource+Functions.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Foundation -import SargonUniFFI - -extension PassphraseFactorSource { - public init( - mnemonicWithPassphrase mwp: MnemonicWithPassphrase - ) { - self = newPassphraseFactorSourceFromMnemonicWithPassphrase(mwp: mwp) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/PasswordFactorSource+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/PasswordFactorSource+Functions.swift new file mode 100644 index 000000000..be3022145 --- /dev/null +++ b/apple/Sources/Sargon/Extensions/Methods/Profile/Factor/PasswordFactorSource+Functions.swift @@ -0,0 +1,14 @@ +import Foundation +import SargonUniFFI + +extension PasswordFactorSource { + public init( + mnemonicWithPassphrase mwp: MnemonicWithPassphrase, + hint: PasswordFactorSourceHint + ) { + self = newPasswordFactorSourceFromMnemonicWithPassphrase( + mwp: mwp, + hint: hint + ) + } +} diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Crypto/Derivation/BIP39/Mnemonic+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Crypto/Derivation/BIP39/Mnemonic+SampleValues.swift index b9518a3d6..b5b256a26 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Crypto/Derivation/BIP39/Mnemonic+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Crypto/Derivation/BIP39/Mnemonic+SampleValues.swift @@ -17,8 +17,8 @@ extension Mnemonic { public static let sampleOffDeviceMnemonicOther: Self = newMnemonicSampleOffDeviceOther() public static let sampleSecurityQuestions: Self = newMnemonicSampleSecurityQuestions() public static let sampleSecurityQuestionsOther: Self = newMnemonicSampleSecurityQuestionsOther() - public static let samplePassphrase: Self = newMnemonicSamplePassphrase() - public static let samplePassphraseOther: Self = newMnemonicSamplePassphraseOther() + public static let samplePassword: Self = newMnemonicSamplePassword() + public static let samplePasswordOther: Self = newMnemonicSamplePasswordOther() public static let sample24ZooVote: Self = try! Self(phrase: "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote") @@ -35,8 +35,8 @@ extension Mnemonic { .sampleOffDeviceMnemonicOther, .sampleSecurityQuestions, .sampleSecurityQuestionsOther, - .samplePassphrase, - .samplePassphraseOther, + .samplePassword, + .samplePasswordOther, ] } #endif // DEBUG diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Factor/FactorSource/PassphraseFactorSource+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Factor/FactorSource/PassphraseFactorSource+SampleValues.swift deleted file mode 100644 index 4b382c868..000000000 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Factor/FactorSource/PassphraseFactorSource+SampleValues.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation -import SargonUniFFI - -#if DEBUG -extension PassphraseFactorSource { - public static let sample: Self = newPassphraseFactorSourceSample() - - public static let sampleOther: Self = newPassphraseFactorSourceSampleOther() -} - -#endif // DEBUG diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Factor/FactorSource/PasswordFactorSource+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Factor/FactorSource/PasswordFactorSource+SampleValues.swift new file mode 100644 index 000000000..660ecbbb4 --- /dev/null +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Factor/FactorSource/PasswordFactorSource+SampleValues.swift @@ -0,0 +1,11 @@ +import Foundation +import SargonUniFFI + +#if DEBUG +extension PasswordFactorSource { + public static let sample: Self = newPasswordFactorSourceSample() + + public static let sampleOther: Self = newPasswordFactorSourceSampleOther() +} + +#endif // DEBUG diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/FactorSource+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/FactorSource+Swiftified.swift index 8834bf605..51f5cdc34 100644 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/FactorSource+Swiftified.swift +++ b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/FactorSource+Swiftified.swift @@ -21,7 +21,7 @@ extension FactorSource: Identifiable { case let .ledger(value): value.id.asGeneral case let .offDeviceMnemonic(value): value.id.asGeneral case let .trustedContact(value): value.id.asGeneral - case let .passphrase(value): value.id.asGeneral + case let .password(value): value.id.asGeneral } } } @@ -40,7 +40,7 @@ extension FactorSource: BaseFactorSourceProtocol { case let .arculusCard(value): value.factorSourceKind case let .offDeviceMnemonic(value): value.factorSourceKind case let .trustedContact(value): value.factorSourceKind - case let .passphrase(value): value.factorSourceKind + case let .password(value): value.factorSourceKind } } @@ -53,7 +53,7 @@ extension FactorSource: BaseFactorSourceProtocol { case let .arculusCard(value): value.common case let .offDeviceMnemonic(value): value.common case let .trustedContact(value): value.common - case let .passphrase(value): value.common + case let .password(value): value.common } } set { @@ -76,9 +76,9 @@ extension FactorSource: BaseFactorSourceProtocol { case var .trustedContact(source): source.common = newValue self = .trustedContact(value: source) - case var .passphrase(source): + case var .password(source): source.common = newValue - self = .passphrase(value: source) + self = .password(value: source) } } } @@ -128,7 +128,7 @@ extension FactorSource: BaseFactorSourceProtocol { extract() } - public var asPassphrase: PassphraseFactorSource? { + public var asPassword: PasswordFactorSource? { extract() } } diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/PassphraseFactorSource+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/PasswordFactorSource+Swiftified.swift similarity index 50% rename from apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/PassphraseFactorSource+Swiftified.swift rename to apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/PasswordFactorSource+Swiftified.swift index b88170a76..f9127293f 100644 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/PassphraseFactorSource+Swiftified.swift +++ b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Factor/FactorSource/PasswordFactorSource+Swiftified.swift @@ -1,25 +1,25 @@ import Foundation import SargonUniFFI -// MARK: - PassphraseFactorSource + SargonModel -extension PassphraseFactorSource: SargonModel {} +// MARK: - PasswordFactorSource + SargonModel +extension PasswordFactorSource: SargonModel {} -// MARK: - PassphraseFactorSource + Identifiable -extension PassphraseFactorSource: Identifiable { +// MARK: - PasswordFactorSource + Identifiable +extension PasswordFactorSource: Identifiable { public typealias ID = FactorSourceIDFromHash } -// MARK: - PassphraseFactorSource + FactorSourceProtocol -extension PassphraseFactorSource: FactorSourceProtocol { - public static let kind: FactorSourceKind = .passphrase +// MARK: - PasswordFactorSource + FactorSourceProtocol +extension PasswordFactorSource: FactorSourceProtocol { + public static let kind: FactorSourceKind = .password public static func extract(from someFactorSource: some BaseFactorSourceProtocol) -> Self? { - guard case let .passphrase(factorSource) = someFactorSource.asGeneral else { return nil } + guard case let .password(factorSource) = someFactorSource.asGeneral else { return nil } return factorSource } public var asGeneral: FactorSource { - .passphrase(value: self) + .password(value: self) } public var factorSourceID: FactorSourceID { @@ -27,7 +27,7 @@ extension PassphraseFactorSource: FactorSourceProtocol { } public var factorSourceKind: FactorSourceKind { - .passphrase + .password } public var supportsOlympia: Bool { asGeneral.supportsOlympia } diff --git a/apple/Tests/TestCases/Profile/Factor/ArculusCardFactorSourceTests.swift b/apple/Tests/TestCases/Profile/Factor/ArculusCardFactorSourceTests.swift index cb76cfa76..2d55cd4b9 100644 --- a/apple/Tests/TestCases/Profile/Factor/ArculusCardFactorSourceTests.swift +++ b/apple/Tests/TestCases/Profile/Factor/ArculusCardFactorSourceTests.swift @@ -18,7 +18,7 @@ final class ArculusCardFactorSourceTests: SpecificFactorSourceTest { XCTAssertEqual(SUT.sample.factorSourceKind, .device) XCTAssertEqual(SUT.sampleOther.factorSourceKind, .ledgerHqHardwareWallet) } + + func test_name() { + XCTAssertEqual(SUT.sample.name, "My Phone") + } } diff --git a/apple/Tests/TestCases/Profile/Factor/LedgerHardwareWalletFactorSourceTests.swift b/apple/Tests/TestCases/Profile/Factor/LedgerHardwareWalletFactorSourceTests.swift index 607b74e36..774d67442 100644 --- a/apple/Tests/TestCases/Profile/Factor/LedgerHardwareWalletFactorSourceTests.swift +++ b/apple/Tests/TestCases/Profile/Factor/LedgerHardwareWalletFactorSourceTests.swift @@ -18,7 +18,7 @@ final class LedgerHardwareWalletFactorSourceTests: SpecificFactorSourceTest { - func test_id_of_passphrase() { +final class PasswordFactorSourceTests: SpecificFactorSourceTest { + func test_id_of_password() { eachSample { sut in XCTAssertEqual(sut.id.description, FactorSourceID.hash(value: sut.id).description) } @@ -15,9 +15,10 @@ final class PassphraseFactorSourceTests: SpecificFactorSourceTest Mnemonic { } #[uniffi::export] -pub fn new_mnemonic_sample_passphrase() -> Mnemonic { - InternalMnemonic::sample_passphrase().into() +pub fn new_mnemonic_sample_password() -> Mnemonic { + InternalMnemonic::sample_password().into() } #[uniffi::export] -pub fn new_mnemonic_sample_passphrase_other() -> Mnemonic { - InternalMnemonic::sample_passphrase_other().into() +pub fn new_mnemonic_sample_password_other() -> Mnemonic { + InternalMnemonic::sample_password_other().into() } diff --git a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_hint.rs b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_hint.rs index b10012670..44bb812eb 100644 --- a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_hint.rs +++ b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_hint.rs @@ -3,8 +3,11 @@ use sargon::ArculusCardHint as InternalArculusCardHint; #[derive(Clone, PartialEq, Eq, Hash, InternalConversion, uniffi::Record)] pub struct ArculusCardHint { + /// A user-assigned name for the arculus card, intended to help users + /// differentiate between multiple arculus cards. + /// /// E.g. "Black" or "Silver" - pub name: String, + pub label: String, pub model: ArculusCardModel, } diff --git a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/mod.rs b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/mod.rs index 3d624cfc4..b2388a1c4 100644 --- a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/mod.rs +++ b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/mod.rs @@ -1,9 +1,11 @@ mod arculus_card_factor_source; mod off_device_mnemonic_factor_source; +mod password_factor_source; mod security_questions_factor_source; mod trusted_contact_factor_source; pub use arculus_card_factor_source::*; pub use off_device_mnemonic_factor_source::*; +pub use password_factor_source::*; pub use security_questions_factor_source::*; pub use trusted_contact_factor_source::*; diff --git a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_factor_source_hint.rs b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_factor_source_hint.rs index 5014b0f53..4d5a3d733 100644 --- a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_factor_source_hint.rs +++ b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_factor_source_hint.rs @@ -5,5 +5,7 @@ use sargon::OffDeviceMnemonicHint as InternalOffDeviceMnemonicHint; /// it and another one. #[derive(Clone, PartialEq, Eq, Hash, InternalConversion, uniffi::Record)] pub struct OffDeviceMnemonicHint { - pub display_name: DisplayName, + /// A user-assigned name for the passphrase, intended to help users + /// differentiate between multiple passphrases. + pub label: DisplayName, } diff --git a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/mod.rs b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/mod.rs new file mode 100644 index 000000000..a9f1bd09d --- /dev/null +++ b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/mod.rs @@ -0,0 +1,5 @@ +mod password_factor_source; +mod password_factor_source_hint; + +pub use password_factor_source::*; +pub use password_factor_source_hint::*; diff --git a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source.rs b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source.rs new file mode 100644 index 000000000..f56c3fa97 --- /dev/null +++ b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source.rs @@ -0,0 +1,42 @@ +use crate::prelude::*; +use sargon::FactorSourceIDFromHash as InternalFactorSourceIDFromHash; +use sargon::PasswordFactorSource as InternalPasswordFactorSource; + +/// NOT IMPLEMENTED NOR USED YET +/// +/// A password based FactorSource is essentially a Input Key Material based Mnemonic, +/// user needs to input the password - key material - every time they use this factor source +#[derive(Clone, PartialEq, Eq, Hash, InternalConversion, uniffi::Record)] +pub struct PasswordFactorSource { + /// Unique and stable identifier of this factor source, stemming from the + /// hash of a special child key of the HD root of the mnemonic. + pub id: FactorSourceIDFromHash, + + /// Common properties shared between FactorSources of different kinds, + /// describing its state, when added, and supported cryptographic parameters. + pub common: FactorSourceCommon, + + /// Properties describing a PasswordFactorSource to help user + /// disambiguate between it and another one. + pub hint: PasswordFactorSourceHint, +} + +#[uniffi::export] +pub fn new_password_factor_source_sample() -> PasswordFactorSource { + InternalPasswordFactorSource::sample().into() +} + +#[uniffi::export] +pub fn new_password_factor_source_sample_other() -> PasswordFactorSource { + InternalPasswordFactorSource::sample_other().into() +} + +#[uniffi::export] +fn new_password_factor_source_from_mnemonic_with_passphrase( + mwp: MnemonicWithPassphrase, + hint: PasswordFactorSourceHint, +) -> PasswordFactorSource { + let id = + InternalFactorSourceIDFromHash::new_for_password(&mwp.into_internal()); + InternalPasswordFactorSource::new(id, hint.into()).into() +} diff --git a/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source_hint.rs b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source_hint.rs new file mode 100644 index 000000000..112630fb8 --- /dev/null +++ b/crates/sargon-uniffi/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source_hint.rs @@ -0,0 +1,9 @@ +use crate::prelude::*; +use sargon::PasswordFactorSourceHint as InternalPasswordFactorSourceHint; + +/// Properties describing a PasswordFactorSource to help user disambiguate between +/// it and another one. +#[derive(Clone, PartialEq, Eq, Hash, InternalConversion, uniffi::Record)] +pub struct PasswordFactorSourceHint { + pub label: String, +} diff --git a/crates/sargon-uniffi/src/profile/mfa/mod.rs b/crates/sargon-uniffi/src/profile/mfa/mod.rs index 458c7b84e..59afd062f 100644 --- a/crates/sargon-uniffi/src/profile/mfa/mod.rs +++ b/crates/sargon-uniffi/src/profile/mfa/mod.rs @@ -1,9 +1,7 @@ mod mfa_factor_sources; -mod passphrase_factor_source; mod secured_entity_control; mod security_structures; pub use mfa_factor_sources::*; -pub use passphrase_factor_source::*; pub use secured_entity_control::*; pub use security_structures::*; diff --git a/crates/sargon-uniffi/src/profile/mfa/passphrase_factor_source/mod.rs b/crates/sargon-uniffi/src/profile/mfa/passphrase_factor_source/mod.rs deleted file mode 100644 index 6ac6b5988..000000000 --- a/crates/sargon-uniffi/src/profile/mfa/passphrase_factor_source/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod passphrase_factor_source; - -pub use passphrase_factor_source::*; diff --git a/crates/sargon-uniffi/src/profile/mfa/passphrase_factor_source/passphrase_factor_source.rs b/crates/sargon-uniffi/src/profile/mfa/passphrase_factor_source/passphrase_factor_source.rs deleted file mode 100644 index 64252e491..000000000 --- a/crates/sargon-uniffi/src/profile/mfa/passphrase_factor_source/passphrase_factor_source.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::prelude::*; -use sargon::FactorSourceIDFromHash as InternalFactorSourceIDFromHash; -use sargon::PassphraseFactorSource as InternalPassphraseFactorSource; - -/// NOT IMPLEMENTED NOR USED YET -/// -/// A passphrase based FactorSource is essentially a Input Key Material based Mnemonic, -/// user needs to input the passphrase - key material - every time they use this factor source -#[derive(Clone, PartialEq, Eq, Hash, InternalConversion, uniffi::Record)] -pub struct PassphraseFactorSource { - /// Unique and stable identifier of this factor source, stemming from the - /// hash of a special child key of the HD root of the mnemonic. - pub id: FactorSourceIDFromHash, - - /// Common properties shared between FactorSources of different kinds, - /// describing its state, when added, and supported cryptographic parameters. - pub common: FactorSourceCommon, -} - -#[uniffi::export] -pub fn new_passphrase_factor_source_sample() -> PassphraseFactorSource { - InternalPassphraseFactorSource::sample().into() -} - -#[uniffi::export] -pub fn new_passphrase_factor_source_sample_other() -> PassphraseFactorSource { - InternalPassphraseFactorSource::sample_other().into() -} - -#[uniffi::export] -fn new_passphrase_factor_source_from_mnemonic_with_passphrase( - mwp: MnemonicWithPassphrase, -) -> PassphraseFactorSource { - let id = InternalFactorSourceIDFromHash::new_for_passphrase( - &mwp.into_internal(), - ); - InternalPassphraseFactorSource::new(id).into() -} diff --git a/crates/sargon-uniffi/src/profile/v100/factors/factor_source.rs b/crates/sargon-uniffi/src/profile/v100/factors/factor_source.rs index d158ae766..0256444e1 100644 --- a/crates/sargon-uniffi/src/profile/v100/factors/factor_source.rs +++ b/crates/sargon-uniffi/src/profile/v100/factors/factor_source.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +use sargon::BaseBaseIsFactorSource; use sargon::BaseIsFactorSource; use sargon::FactorSource as InternalFactorSource; @@ -30,8 +31,8 @@ pub enum FactorSource { value: TrustedContactFactorSource, }, - Passphrase { - value: PassphraseFactorSource, + Password { + value: PasswordFactorSource, }, } @@ -50,6 +51,11 @@ pub fn factor_source_supports_babylon(factor_source: &FactorSource) -> bool { factor_source.into_internal().supports_babylon() } +#[uniffi::export] +pub fn factor_source_name(factor_source: &FactorSource) -> String { + factor_source.into_internal().name() +} + #[uniffi::export] pub fn new_factor_source_sample() -> FactorSource { InternalFactorSource::sample().into() diff --git a/crates/sargon-uniffi/src/profile/v100/factors/factor_source_kind.rs b/crates/sargon-uniffi/src/profile/v100/factors/factor_source_kind.rs index b3a27b243..2cf0ad7d2 100644 --- a/crates/sargon-uniffi/src/profile/v100/factors/factor_source_kind.rs +++ b/crates/sargon-uniffi/src/profile/v100/factors/factor_source_kind.rs @@ -73,7 +73,7 @@ pub enum FactorSourceKind { /// * Mine /// * Off device /// * Hierarchical deterministic (IKM -> HKDF -> Mnemonic) - Passphrase, + Password, } delegate_display_debug_into!(FactorSourceKind, InternalFactorSourceKind); diff --git a/crates/sargon-uniffi/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source_hint.rs b/crates/sargon-uniffi/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source_hint.rs index 83b0cc77b..88a50a2a5 100644 --- a/crates/sargon-uniffi/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source_hint.rs +++ b/crates/sargon-uniffi/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source_hint.rs @@ -5,8 +5,16 @@ use sargon::DeviceFactorSourceHint as InternalDeviceFactorSourceHint; /// it and another one. #[derive(Clone, PartialEq, Eq, Hash, InternalConversion, uniffi::Record)] pub struct DeviceFactorSourceHint { - /// "iPhone RED" - pub name: String, + /// A user-assigned name for the device, intended to help users + /// differentiate between multiple devices. + /// + /// Example: "My Phone" + pub label: String, + + /// The name of the device as provided by the system. + /// + /// Example: "iPhone RED" + pub device_name: String, /// "iPhone SE 2nd gen" pub model: String, diff --git a/crates/sargon-uniffi/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_hint.rs b/crates/sargon-uniffi/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_hint.rs index a8011e0a7..235f18f55 100644 --- a/crates/sargon-uniffi/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_hint.rs +++ b/crates/sargon-uniffi/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_hint.rs @@ -3,8 +3,11 @@ use sargon::LedgerHardwareWalletHint as InternalLedgerHardwareWalletHint; #[derive(Clone, PartialEq, Eq, Hash, InternalConversion, uniffi::Record)] pub struct LedgerHardwareWalletHint { - /// "Orange, scratched" - pub name: String, + /// A user-assigned name for the ledger, intended to help users + /// differentiate between multiple ledgers. + /// + /// E.g. "Orange, scratched" + pub label: String, /// E.g. `nanoS+` pub model: LedgerHardwareWalletModel, diff --git a/crates/sargon/Cargo.toml b/crates/sargon/Cargo.toml index 0e53a17db..f7d675a15 100644 --- a/crates/sargon/Cargo.toml +++ b/crates/sargon/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sargon" # Don't forget to update version in crates/sargon-uniffi/Cargo.toml -version = "1.1.69" +version = "1.1.70" edition = "2021" build = "build.rs" diff --git a/crates/sargon/src/core/error/common_error.rs b/crates/sargon/src/core/error/common_error.rs index 6c9ff9d2a..b7bc32764 100644 --- a/crates/sargon/src/core/error/common_error.rs +++ b/crates/sargon/src/core/error/common_error.rs @@ -658,8 +658,8 @@ pub enum CommonError { #[error("Empty FactorSources list")] FactorSourcesOfKindEmptyFactors = 10184, - #[error("Expected Passphrase factor source got something else")] - ExpectedPassphraseFactorSourceGotSomethingElse = 10185, + #[error("Expected Password factor source got something else")] + ExpectedPasswordFactorSourceGotSomethingElse = 10185, #[error("Unknown persona.")] UnknownPersona = 10186, diff --git a/crates/sargon/src/factor_instances_provider/factor_instances_cache/factor_instances_cache.rs b/crates/sargon/src/factor_instances_provider/factor_instances_cache/factor_instances_cache.rs index e5b1c9483..85705106a 100644 --- a/crates/sargon/src/factor_instances_provider/factor_instances_cache/factor_instances_cache.rs +++ b/crates/sargon/src/factor_instances_provider/factor_instances_cache/factor_instances_cache.rs @@ -538,7 +538,7 @@ mod tests { let sut = SUT::default(); assert!(sut .insert_all(&IndexMap::kv( - FactorSourceIDFromHash::sample_passphrase_other(), + FactorSourceIDFromHash::sample_password_other(), FactorInstances::sample() )) .is_err()) diff --git a/crates/sargon/src/factor_instances_provider/provider/factor_instances_provider_unit_tests.rs b/crates/sargon/src/factor_instances_provider/provider/factor_instances_provider_unit_tests.rs index f9871191e..cbcc03627 100644 --- a/crates/sargon/src/factor_instances_provider/provider/factor_instances_provider_unit_tests.rs +++ b/crates/sargon/src/factor_instances_provider/provider/factor_instances_provider_unit_tests.rs @@ -944,10 +944,10 @@ async fn test_securified_accounts() { let bdfs = FactorSource::from(os.bdfs().unwrap()); let ledger = FactorSource::sample_ledger(); let arculus = FactorSource::sample_arculus(); - let passphrase = FactorSource::sample_passphrase(); + let password = FactorSource::sample_password(); os.add_factor_source(ledger.clone()).await.unwrap(); os.add_factor_source(arculus.clone()).await.unwrap(); - os.add_factor_source(passphrase.clone()).await.unwrap(); + os.add_factor_source(password.clone()).await.unwrap(); let matrix_0 = MatrixOfFactorSources::new( PrimaryRoleWithFactorSources::threshold_factors_only( @@ -1087,11 +1087,11 @@ async fn test_securified_accounts() { ); let matrix_1 = MatrixOfFactorSources::new( - PrimaryRoleWithFactorSources::override_only([passphrase.clone()]) + PrimaryRoleWithFactorSources::override_only([password.clone()]) .unwrap(), - RecoveryRoleWithFactorSources::override_only([passphrase.clone()]) + RecoveryRoleWithFactorSources::override_only([password.clone()]) .unwrap(), - ConfirmationRoleWithFactorSources::override_only([passphrase.clone()]) + ConfirmationRoleWithFactorSources::override_only([password.clone()]) .unwrap(), ) .unwrap(); @@ -1125,7 +1125,7 @@ async fn test_securified_accounts() { .into_iter() .map(|f| f.factor_source_id) .collect_vec(), - [passphrase.factor_source_id(),] + [password.factor_source_id(),] ); for factors_for_role in [ @@ -1170,7 +1170,7 @@ async fn test_securified_accounts() { .into_iter() .map(|f| f.factor_source_id) .collect_vec(), - [passphrase.factor_source_id(),] + [password.factor_source_id(),] ); for factors_for_role in [ @@ -1334,10 +1334,10 @@ async fn securify_accounts_when_cache_is_half_full_multiple_factor_sources() { let (os, bdfs) = SargonOS::with_bdfs().await; let ledger = FactorSource::sample_ledger(); let arculus = FactorSource::sample_arculus(); - let passphrase = FactorSource::sample_passphrase(); + let password = FactorSource::sample_password(); os.add_factor_source(ledger.clone()).await.unwrap(); os.add_factor_source(arculus.clone()).await.unwrap(); - os.add_factor_source(passphrase.clone()).await.unwrap(); + os.add_factor_source(password.clone()).await.unwrap(); let profile = os.profile().unwrap(); let factor_sources = profile.factor_sources.clone(); @@ -1347,7 +1347,7 @@ async fn securify_accounts_when_cache_is_half_full_multiple_factor_sources() { bdfs.clone(), ledger.clone(), arculus.clone(), - passphrase.clone(), + password.clone(), ] ); @@ -1802,10 +1802,10 @@ async fn securified_personas() { let bdfs = FactorSource::from(os.bdfs().unwrap()); let ledger = FactorSource::sample_ledger(); let arculus = FactorSource::sample_arculus(); - let passphrase = FactorSource::sample_passphrase(); + let password = FactorSource::sample_password(); os.add_factor_source(ledger.clone()).await.unwrap(); os.add_factor_source(arculus.clone()).await.unwrap(); - os.add_factor_source(passphrase.clone()).await.unwrap(); + os.add_factor_source(password.clone()).await.unwrap(); let matrix_0 = MatrixOfFactorSources::new( PrimaryRoleWithFactorSources::threshold_factors_only( @@ -1946,11 +1946,11 @@ async fn securified_personas() { ); let matrix_1 = MatrixOfFactorSources::new( - PrimaryRoleWithFactorSources::override_only([passphrase.clone()]) + PrimaryRoleWithFactorSources::override_only([password.clone()]) .unwrap(), - RecoveryRoleWithFactorSources::override_only([passphrase.clone()]) + RecoveryRoleWithFactorSources::override_only([password.clone()]) .unwrap(), - ConfirmationRoleWithFactorSources::override_only([passphrase.clone()]) + ConfirmationRoleWithFactorSources::override_only([password.clone()]) .unwrap(), ) .unwrap(); @@ -1989,7 +1989,7 @@ async fn securified_personas() { .into_iter() .map(|f| f.factor_source_id) .collect_vec(), - [passphrase.factor_source_id(),] + [password.factor_source_id(),] ); for factors_for_role in [ @@ -2033,7 +2033,7 @@ async fn securified_personas() { .into_iter() .map(|f| f.factor_source_id) .collect_vec(), - [passphrase.factor_source_id(),] + [password.factor_source_id(),] ); for factors_for_role in [ diff --git a/crates/sargon/src/hierarchical_deterministic/bip39/mnemonic.rs b/crates/sargon/src/hierarchical_deterministic/bip39/mnemonic.rs index efbb17698..fac358211 100644 --- a/crates/sargon/src/hierarchical_deterministic/bip39/mnemonic.rs +++ b/crates/sargon/src/hierarchical_deterministic/bip39/mnemonic.rs @@ -333,7 +333,7 @@ impl Mnemonic { /// * music /// * project /// * uphold - pub fn sample_passphrase() -> Self { + pub fn sample_password() -> Self { Self::from_phrase("pass phrase sign source sample pass phrase sign source sample pass phrase sign source sample pass phrase sign source sample pass phrase sample soon").expect("Valid mnemonic") } #[allow(dead_code)] @@ -345,7 +345,7 @@ impl Mnemonic { /// * once /// * ripple /// * summer - pub fn sample_passphrase_other() -> Self { + pub fn sample_password_other() -> Self { Self::from_phrase("pass phrase sign source sample other pass phrase sign source sample other pass phrase sign source sample other pass phrase source sample other usual").expect("Valid mnemonic") } } diff --git a/crates/sargon/src/hierarchical_deterministic/derivation/mnemonic_with_passphrase.rs b/crates/sargon/src/hierarchical_deterministic/derivation/mnemonic_with_passphrase.rs index 38bc7684b..5ec07f262 100644 --- a/crates/sargon/src/hierarchical_deterministic/derivation/mnemonic_with_passphrase.rs +++ b/crates/sargon/src/hierarchical_deterministic/derivation/mnemonic_with_passphrase.rs @@ -217,16 +217,16 @@ impl MnemonicWithPassphrase { ) } - pub(crate) fn sample_passphrase() -> Self { + pub(crate) fn sample_password() -> Self { Self::with_passphrase( - Mnemonic::sample_passphrase(), + Mnemonic::sample_password(), BIP39Passphrase::default(), ) } - pub(crate) fn sample_passphrase_other() -> Self { + pub(crate) fn sample_password_other() -> Self { Self::with_passphrase( - Mnemonic::sample_security_questions_other(), + Mnemonic::sample_password_other(), BIP39Passphrase::new("Pass phrase"), ) } diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_factor_source.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_factor_source.rs index 43a37915d..58be140c3 100644 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_factor_source.rs +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_factor_source.rs @@ -92,7 +92,7 @@ impl IsFactorSource for ArculusCardFactorSource { FactorSourceKind::ArculusCard } } -impl BaseIsFactorSource for ArculusCardFactorSource { +impl BaseBaseIsFactorSource for ArculusCardFactorSource { fn common_properties(&self) -> FactorSourceCommon { self.common.clone() } @@ -108,6 +108,10 @@ impl BaseIsFactorSource for ArculusCardFactorSource { fn set_common_properties(&mut self, updated: FactorSourceCommon) { self.common = updated } + + fn name(&self) -> String { + self.hint.label.clone() + } } #[cfg(test)] @@ -149,7 +153,7 @@ mod tests { "lastUsedOn": "2023-09-11T16:05:56.000Z" }, "hint": { - "name": "Silver", + "label": "Silver", "model": "arculusColdStorageWallet" } } @@ -188,4 +192,9 @@ mod tests { fn factor_source_kind() { assert_eq!(SUT::sample().factor_source_kind(), SUT::sample().id.kind); } + + #[test] + fn name() { + assert_eq!(SUT::sample().name(), "Silver"); + } } diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_hint.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_hint.rs index db88b9ead..187ae1f9e 100644 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_hint.rs +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/arculus_card_factor_source/arculus_card_hint.rs @@ -10,18 +10,21 @@ use crate::prelude::*; Hash, derive_more::Display, )] -#[display("{name} {model}")] +#[display("{label} {model}")] pub struct ArculusCardHint { + /// A user-assigned name for the arculus card, intended to help users + /// differentiate between multiple arculus cards. + /// /// E.g. "Black" or "Silver" - pub name: String, + pub label: String, pub model: ArculusCardModel, } impl ArculusCardHint { - pub fn new(name: &str, model: ArculusCardModel) -> Self { + pub fn new(label: &str, model: ArculusCardModel) -> Self { Self { - name: name.to_string(), + label: label.to_string(), model, } } @@ -62,7 +65,7 @@ mod tests { &model, r#" { - "name": "Silver", + "label": "Silver", "model": "arculusColdStorageWallet" } "#, diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/mod.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/mod.rs index abdda9268..b2388a1c4 100644 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/mod.rs +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/mod.rs @@ -1,11 +1,11 @@ mod arculus_card_factor_source; mod off_device_mnemonic_factor_source; -mod passphrase_factor_source; +mod password_factor_source; mod security_questions_factor_source; mod trusted_contact_factor_source; pub use arculus_card_factor_source::*; pub use off_device_mnemonic_factor_source::*; -pub use passphrase_factor_source::*; +pub use password_factor_source::*; pub use security_questions_factor_source::*; pub use trusted_contact_factor_source::*; diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_factor_source_hint.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_factor_source_hint.rs index cd0056f72..ed951b9eb 100644 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_factor_source_hint.rs +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_factor_source_hint.rs @@ -14,12 +14,14 @@ use crate::prelude::*; )] #[serde(rename_all = "camelCase")] pub struct OffDeviceMnemonicHint { - pub display_name: DisplayName, + /// A user-assigned name for the passphrase, intended to help users + /// differentiate between multiple passphrases. + pub label: DisplayName, } impl OffDeviceMnemonicHint { - pub fn new(display_name: DisplayName) -> Self { - Self { display_name } + pub fn new(label: DisplayName) -> Self { + Self { label } } } diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_mnemonic_factor_source.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_mnemonic_factor_source.rs index 45293c2a9..b28603857 100644 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_mnemonic_factor_source.rs +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/off_device_mnemonic_factor_source/off_device_mnemonic_factor_source.rs @@ -92,7 +92,7 @@ impl IsFactorSource for OffDeviceMnemonicFactorSource { FactorSourceKind::OffDeviceMnemonic } } -impl BaseIsFactorSource for OffDeviceMnemonicFactorSource { +impl BaseBaseIsFactorSource for OffDeviceMnemonicFactorSource { fn common_properties(&self) -> FactorSourceCommon { self.common.clone() } @@ -108,6 +108,10 @@ impl BaseIsFactorSource for OffDeviceMnemonicFactorSource { fn set_common_properties(&mut self, updated: FactorSourceCommon) { self.common = updated } + + fn name(&self) -> String { + self.hint.label.value.clone() + } } #[cfg(test)] @@ -151,4 +155,9 @@ mod tests { }) ); } + + #[test] + fn name() { + assert_eq!(SUT::sample().name(), "Story about a horse"); + } } diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/passphrase_factor_source/mod.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/passphrase_factor_source/mod.rs deleted file mode 100644 index 6ac6b5988..000000000 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/passphrase_factor_source/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod passphrase_factor_source; - -pub use passphrase_factor_source::*; diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/mod.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/mod.rs new file mode 100644 index 000000000..a9f1bd09d --- /dev/null +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/mod.rs @@ -0,0 +1,5 @@ +mod password_factor_source; +mod password_factor_source_hint; + +pub use password_factor_source::*; +pub use password_factor_source_hint::*; diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/passphrase_factor_source/passphrase_factor_source.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source.rs similarity index 61% rename from crates/sargon/src/profile/mfa/mfa_factor_sources/passphrase_factor_source/passphrase_factor_source.rs rename to crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source.rs index ffe92ce6a..33fbdfab7 100644 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/passphrase_factor_source/passphrase_factor_source.rs +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source.rs @@ -2,8 +2,8 @@ use crate::prelude::*; /// NOT IMPLEMENTED NOR USED YET /// -/// A passphrase based FactorSource is essentially a Input Key Material based Mnemonic, -/// user needs to input the passphrase - key material - every time they use this factor source +/// A password based FactorSource is essentially a Input Key Material based Mnemonic, +/// user needs to input the password - key material - every time they use this factor source #[derive( Serialize, Deserialize, @@ -16,7 +16,7 @@ use crate::prelude::*; )] #[serde(rename_all = "camelCase")] #[display("{id}")] -pub struct PassphraseFactorSource { +pub struct PasswordFactorSource { /// Unique and stable identifier of this factor source, stemming from the /// hash of a special child key of the HD root of the mnemonic. pub id: FactorSourceIDFromHash, @@ -24,65 +24,77 @@ pub struct PassphraseFactorSource { /// Common properties shared between FactorSources of different kinds, /// describing its state, when added, and supported cryptographic parameters. pub common: FactorSourceCommon, + + /// Properties describing a PasswordFactorSource to help user + /// disambiguate between it and another one. + pub hint: PasswordFactorSourceHint, } -impl PassphraseFactorSource { - /// Instantiates a new `PassphraseFactorSource` - pub fn new(id: FactorSourceIDFromHash) -> Self { +impl PasswordFactorSource { + /// Instantiates a new `PasswordFactorSource` + pub fn new( + id: FactorSourceIDFromHash, + hint: PasswordFactorSourceHint, + ) -> Self { Self { id, common: FactorSourceCommon::new_bdfs(false), + hint, } } } -impl From for FactorSource { - fn from(value: PassphraseFactorSource) -> Self { - FactorSource::Passphrase { value } +impl From for FactorSource { + fn from(value: PasswordFactorSource) -> Self { + FactorSource::Password { value } } } -fn new_passphrase_with_mwp( +fn new_password_with_mwp( mwp: MnemonicWithPassphrase, -) -> PassphraseFactorSource { - let id = FactorSourceIDFromHash::new_for_passphrase(&mwp); - let mut source = PassphraseFactorSource::new(id); + hint: PasswordFactorSourceHint, +) -> PasswordFactorSource { + let id = FactorSourceIDFromHash::new_for_password(&mwp); + let mut source = PasswordFactorSource::new(id, hint); source.common.last_used_on = Timestamp::sample(); source.common.added_on = Timestamp::sample(); source } -impl HasSampleValues for PassphraseFactorSource { +impl HasSampleValues for PasswordFactorSource { fn sample() -> Self { - new_passphrase_with_mwp(MnemonicWithPassphrase::sample_passphrase()) + new_password_with_mwp( + MnemonicWithPassphrase::sample_password(), + PasswordFactorSourceHint::sample(), + ) } fn sample_other() -> Self { - new_passphrase_with_mwp( - MnemonicWithPassphrase::sample_passphrase_other(), + new_password_with_mwp( + MnemonicWithPassphrase::sample_password_other(), + PasswordFactorSourceHint::sample_other(), ) } } -impl TryFrom for PassphraseFactorSource { +impl TryFrom for PasswordFactorSource { type Error = CommonError; fn try_from(value: FactorSource) -> Result { match value { - FactorSource::Passphrase { value } => Ok(value), - _ => { - Err(Self::Error::ExpectedPassphraseFactorSourceGotSomethingElse) - } + FactorSource::Password { value } => Ok(value), + _ => Err(Self::Error::ExpectedPasswordFactorSourceGotSomethingElse), } } } -impl IsFactorSource for PassphraseFactorSource { +impl IsFactorSource for PasswordFactorSource { fn kind() -> FactorSourceKind { - FactorSourceKind::Passphrase + FactorSourceKind::Password } } -impl BaseIsFactorSource for PassphraseFactorSource { + +impl BaseBaseIsFactorSource for PasswordFactorSource { fn factor_source_kind(&self) -> FactorSourceKind { self.id.kind } @@ -98,6 +110,10 @@ impl BaseIsFactorSource for PassphraseFactorSource { fn set_common_properties(&mut self, updated: FactorSourceCommon) { self.common = updated } + + fn name(&self) -> String { + self.hint.label.clone() + } } #[cfg(test)] @@ -105,7 +121,7 @@ mod tests { use super::*; #[allow(clippy::upper_case_acronyms)] - type SUT = PassphraseFactorSource; + type SUT = PasswordFactorSource; #[test] fn equality() { @@ -126,7 +142,7 @@ mod tests { r#" { "id": { - "kind": "passphrase", + "kind": "password", "body": "181ab662e19fac3ad9f08d5c673b286d4a5ed9cd3762356dc9831dc42427c1b9" }, "common": { @@ -137,6 +153,9 @@ mod tests { }, "flags": [], "lastUsedOn": "2023-09-11T16:05:56.000Z" + }, + "hint": { + "label": "Password 1" } } "#, @@ -152,7 +171,7 @@ mod tests { #[test] fn kind() { - assert_eq!(SUT::kind(), FactorSourceKind::Passphrase); + assert_eq!(SUT::kind(), FactorSourceKind::Password); } #[test] @@ -161,7 +180,7 @@ mod tests { let factor_source: FactorSource = wrong.clone().into(); assert_eq!( SUT::try_from(factor_source), - Err(CommonError::ExpectedPassphraseFactorSourceGotSomethingElse) + Err(CommonError::ExpectedPasswordFactorSourceGotSomethingElse) ); } @@ -174,4 +193,9 @@ mod tests { fn factor_source_kind() { assert_eq!(SUT::sample().factor_source_kind(), SUT::sample().id.kind); } + + #[test] + fn name() { + assert_eq!(SUT::sample().name(), "Password 1"); + } } diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source_hint.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source_hint.rs new file mode 100644 index 000000000..b62a116ee --- /dev/null +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/password_factor_source/password_factor_source_hint.rs @@ -0,0 +1,56 @@ +use crate::prelude::*; + +/// Properties describing a PasswordFactorSource to help user disambiguate between +/// it and another one. +#[derive( + Serialize, + Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + derive_more::Display, +)] +pub struct PasswordFactorSourceHint { + /// A user-assigned name for the password, intended to help users + /// differentiate between multiple passwords. + pub label: String, +} + +impl PasswordFactorSourceHint { + pub fn new(label: impl AsRef) -> Self { + Self { + label: label.as_ref().to_owned(), + } + } +} + +impl HasSampleValues for PasswordFactorSourceHint { + fn sample() -> Self { + Self::new("Password 1") + } + + fn sample_other() -> Self { + Self::new("Password 2") + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = PasswordFactorSourceHint; + + #[test] + fn equality() { + assert_eq!(SUT::sample(), SUT::sample()); + assert_eq!(SUT::sample_other(), SUT::sample_other()); + } + + #[test] + fn inequality() { + assert_ne!(SUT::sample(), SUT::sample_other()); + } +} diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/security_questions_factor_source/security_questions_factor_source.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/security_questions_factor_source/security_questions_factor_source.rs index ae2f66a53..54840fdcb 100644 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/security_questions_factor_source/security_questions_factor_source.rs +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/security_questions_factor_source/security_questions_factor_source.rs @@ -261,7 +261,7 @@ impl IsFactorSource for SecurityQuestions_NOT_PRODUCTION_READY_FactorSource { FactorSourceKind::SecurityQuestions } } -impl BaseIsFactorSource +impl BaseBaseIsFactorSource for SecurityQuestions_NOT_PRODUCTION_READY_FactorSource { fn common_properties(&self) -> FactorSourceCommon { @@ -279,6 +279,18 @@ impl BaseIsFactorSource fn set_common_properties(&mut self, updated: FactorSourceCommon) { self.common = updated } + + fn name(&self) -> String { + let ids = self + .sealed_mnemonic + .security_questions + .items() + .into_iter() + .map(|q| q.id()) + .map(|id| format!("#{:?}", id)) + .join(", "); + format!("Questions: {}", ids) + } } #[cfg(test)] @@ -481,4 +493,9 @@ mod tests { }) ); } + + #[test] + fn name() { + assert_eq!(SUT::sample().name(), "Questions: #0, #1, #2, #3, #4, #5"); + } } diff --git a/crates/sargon/src/profile/mfa/mfa_factor_sources/trusted_contact_factor_source/trusted_contact_factor_source.rs b/crates/sargon/src/profile/mfa/mfa_factor_sources/trusted_contact_factor_source/trusted_contact_factor_source.rs index 33071d038..1a8dfa422 100644 --- a/crates/sargon/src/profile/mfa/mfa_factor_sources/trusted_contact_factor_source/trusted_contact_factor_source.rs +++ b/crates/sargon/src/profile/mfa/mfa_factor_sources/trusted_contact_factor_source/trusted_contact_factor_source.rs @@ -71,7 +71,7 @@ impl IsFactorSource for TrustedContactFactorSource { FactorSourceKind::TrustedContact } } -impl BaseIsFactorSource for TrustedContactFactorSource { +impl BaseBaseIsFactorSource for TrustedContactFactorSource { fn common_properties(&self) -> FactorSourceCommon { self.common.clone() } @@ -87,6 +87,10 @@ impl BaseIsFactorSource for TrustedContactFactorSource { fn set_common_properties(&mut self, updated: FactorSourceCommon) { self.common = updated } + + fn name(&self) -> String { + self.contact.name.value.clone() + } } impl TrustedContactFactorSource { fn new_sample(name: &str, email: &str, address: AccountAddress) -> Self { @@ -208,4 +212,9 @@ mod tests { }) ); } + + #[test] + fn name() { + assert_eq!(SUT::sample().name(), "Spending Account"); + } } diff --git a/crates/sargon/src/profile/v100/factors/factor_source.rs b/crates/sargon/src/profile/v100/factors/factor_source.rs index 21c6d2f09..7e1b67e9a 100644 --- a/crates/sargon/src/profile/v100/factors/factor_source.rs +++ b/crates/sargon/src/profile/v100/factors/factor_source.rs @@ -49,10 +49,10 @@ pub enum FactorSource { value: TrustedContactFactorSource, }, - Passphrase { - #[serde(rename = "passphrase")] - #[display("Passphrase({value})")] - value: PassphraseFactorSource, + Password { + #[serde(rename = "password")] + #[display("Password({value})")] + value: PasswordFactorSource, }, } @@ -64,81 +64,57 @@ impl IsMaybeKeySpaceAware for FactorSource { } } -impl BaseIsFactorSource for FactorSource { - fn set_common_properties(&mut self, updated: FactorSourceCommon) { +impl FactorSource { + fn map_get( + &self, + map: impl FnOnce(&dyn BaseBaseIsFactorSource) -> R, + ) -> R { match self { - FactorSource::Device { value } => { - value.set_common_properties(updated) - } - FactorSource::Ledger { value } => { - value.set_common_properties(updated) - } - FactorSource::SecurityQuestions { value } => { - value.set_common_properties(updated) - } - FactorSource::ArculusCard { value } => { - value.set_common_properties(updated) - } - FactorSource::OffDeviceMnemonic { value } => { - value.set_common_properties(updated) - } - FactorSource::TrustedContact { value } => { - value.set_common_properties(updated) - } - FactorSource::Passphrase { value } => { - value.set_common_properties(updated) - } + FactorSource::Device { ref value } => map(value), + FactorSource::ArculusCard { ref value } => map(value), + FactorSource::Ledger { ref value } => map(value), + FactorSource::OffDeviceMnemonic { ref value } => map(value), + FactorSource::SecurityQuestions { ref value } => map(value), + FactorSource::TrustedContact { ref value } => map(value), + FactorSource::Password { ref value } => map(value), } } - fn common_properties(&self) -> FactorSourceCommon { + fn map_set( + &mut self, + mut map: impl FnMut(&mut dyn BaseBaseIsFactorSource), + ) { match self { - FactorSource::Device { value } => value.common_properties(), - FactorSource::Ledger { value } => value.common_properties(), - FactorSource::SecurityQuestions { value } => { - value.common_properties() - } - FactorSource::ArculusCard { value } => value.common_properties(), - FactorSource::OffDeviceMnemonic { value } => { - value.common_properties() - } - FactorSource::TrustedContact { value } => value.common_properties(), - FactorSource::Passphrase { value } => value.common_properties(), + FactorSource::Device { ref mut value } => map(value), + FactorSource::ArculusCard { ref mut value } => map(value), + FactorSource::Ledger { ref mut value } => map(value), + FactorSource::OffDeviceMnemonic { ref mut value } => map(value), + FactorSource::SecurityQuestions { ref mut value } => map(value), + FactorSource::TrustedContact { ref mut value } => map(value), + FactorSource::Password { ref mut value } => map(value), } } +} + +impl BaseBaseIsFactorSource for FactorSource { + fn set_common_properties(&mut self, updated: FactorSourceCommon) { + self.map_set(|v| v.set_common_properties(updated.clone())); + } + + fn common_properties(&self) -> FactorSourceCommon { + self.map_get(|v| v.common_properties()) + } fn factor_source_kind(&self) -> FactorSourceKind { - match self { - FactorSource::Device { value } => value.factor_source_kind(), - FactorSource::Ledger { value } => value.factor_source_kind(), - FactorSource::SecurityQuestions { value } => { - value.factor_source_kind() - } - FactorSource::ArculusCard { value } => value.factor_source_kind(), - FactorSource::OffDeviceMnemonic { value } => { - value.factor_source_kind() - } - FactorSource::TrustedContact { value } => { - value.factor_source_kind() - } - FactorSource::Passphrase { value } => value.factor_source_kind(), - } + self.map_get(|v| v.factor_source_kind()) } fn factor_source_id(&self) -> FactorSourceID { - match self { - FactorSource::Device { value } => value.factor_source_id(), - FactorSource::Ledger { value } => value.factor_source_id(), - FactorSource::SecurityQuestions { value } => { - value.factor_source_id() - } - FactorSource::ArculusCard { value } => value.factor_source_id(), - FactorSource::OffDeviceMnemonic { value } => { - value.factor_source_id() - } - FactorSource::TrustedContact { value } => value.factor_source_id(), - FactorSource::Passphrase { value } => value.factor_source_id(), - } + self.map_get(|v| v.factor_source_id()) + } + + fn name(&self) -> String { + self.map_get(|v| v.name()) } } @@ -250,8 +226,8 @@ impl Serialize for FactorSource { state.serialize_field(discriminator_key, discriminant)?; state.serialize_field(discriminant, value)?; } - FactorSource::Passphrase { value } => { - let discriminant = "passphrase"; + FactorSource::Password { value } => { + let discriminant = "password"; state.serialize_field(discriminator_key, discriminant)?; state.serialize_field(discriminant, value)?; } @@ -304,8 +280,8 @@ impl FactorSource { Self::sample_trusted_contact_radix(), Self::sample_security_questions(), Self::sample_security_questions_other(), - Self::sample_passphrase(), - Self::sample_passphrase_other(), + Self::sample_password(), + Self::sample_password_other(), ] } pub fn sample_device() -> Self { @@ -372,12 +348,12 @@ impl FactorSource { ) } - pub fn sample_passphrase() -> Self { - Self::from(PassphraseFactorSource::sample()) + pub fn sample_password() -> Self { + Self::from(PasswordFactorSource::sample()) } - pub fn sample_passphrase_other() -> Self { - Self::from(PassphraseFactorSource::sample_other()) + pub fn sample_password_other() -> Self { + Self::from(PasswordFactorSource::sample_other()) } } @@ -412,6 +388,16 @@ mod tests { ) } + #[test] + fn name() { + assert_eq!(SUT::sample().name(), DeviceFactorSource::sample().name()); + + assert_eq!( + SUT::sample_other().name(), + LedgerHardwareWalletFactorSource::sample().name() + ) + } + #[test] fn factor_source_id_device() { assert_eq!( @@ -490,10 +476,10 @@ mod tests { } #[test] - fn factor_source_kind_passphrase() { + fn factor_source_kind_password() { assert_eq!( - SUT::sample_passphrase().factor_source_kind(), - FactorSourceKind::Passphrase + SUT::sample_password().factor_source_kind(), + FactorSourceKind::Password ); } diff --git a/crates/sargon/src/profile/v100/factors/factor_source_id_from_hash.rs b/crates/sargon/src/profile/v100/factors/factor_source_id_from_hash.rs index 1d695adeb..8be286f24 100644 --- a/crates/sargon/src/profile/v100/factors/factor_source_id_from_hash.rs +++ b/crates/sargon/src/profile/v100/factors/factor_source_id_from_hash.rs @@ -119,11 +119,11 @@ impl FactorSourceIDFromHash { ) } - pub fn new_for_passphrase( + pub fn new_for_password( mnemonic_with_passphrase: &MnemonicWithPassphrase, ) -> Self { Self::from_mnemonic_with_passphrase( - FactorSourceKind::Passphrase, + FactorSourceKind::Password, mnemonic_with_passphrase, ) } @@ -206,14 +206,12 @@ impl FactorSourceIDFromHash { ) } - pub fn sample_passphrase() -> Self { - Self::new_for_passphrase(&MnemonicWithPassphrase::sample_passphrase()) + pub fn sample_password() -> Self { + Self::new_for_password(&MnemonicWithPassphrase::sample_password()) } - pub fn sample_passphrase_other() -> Self { - Self::new_for_passphrase( - &MnemonicWithPassphrase::sample_passphrase_other(), - ) + pub fn sample_password_other() -> Self { + Self::new_for_password(&MnemonicWithPassphrase::sample_password_other()) } } diff --git a/crates/sargon/src/profile/v100/factors/factor_source_kind.rs b/crates/sargon/src/profile/v100/factors/factor_source_kind.rs index 2a2972c58..e4f5a5b91 100644 --- a/crates/sargon/src/profile/v100/factors/factor_source_kind.rs +++ b/crates/sargon/src/profile/v100/factors/factor_source_kind.rs @@ -47,8 +47,8 @@ pub enum FactorSourceKind { /// * Mine /// * Off device /// * Hierarchical deterministic (IKM -> HKDF -> Mnemonic) - #[serde(rename = "passphrase")] - Passphrase, + #[serde(rename = "password")] + Password, /// An encrypted user owned mnemonic (*never* any BIP39 passphrase) which can /// be decrypted by answers to **security question**, which are personal questions @@ -153,7 +153,7 @@ mod tests { eq(OffDeviceMnemonic, "offDeviceMnemonic"); eq(TrustedContact, "trustedContact"); eq(SecurityQuestions, "securityQuestions"); - eq(Passphrase, "passphrase"); + eq(Password, "password"); } #[test] @@ -202,7 +202,7 @@ mod tests { assert_eq!(SUT::OffDeviceMnemonic.discriminant(), "offDeviceMnemonic"); assert_eq!(SUT::TrustedContact.discriminant(), "trustedContact"); - assert_eq!(SUT::Passphrase.discriminant(), "passphrase"); + assert_eq!(SUT::Password.discriminant(), "password"); } #[test] @@ -224,7 +224,7 @@ mod tests { format!("{}", SUT::TrustedContact.discriminant()), "trustedContact" ); - assert_eq!(format!("{}", SUT::Passphrase.discriminant()), "passphrase"); + assert_eq!(format!("{}", SUT::Password.discriminant()), "password"); } #[test] @@ -246,10 +246,7 @@ mod tests { &SUT::OffDeviceMnemonic, json!("offDeviceMnemonic"), ); - assert_json_value_eq_after_roundtrip( - &SUT::Passphrase, - json!("passphrase"), - ); + assert_json_value_eq_after_roundtrip(&SUT::Password, json!("password")); assert_json_roundtrip(&SUT::Device); } } diff --git a/crates/sargon/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source.rs b/crates/sargon/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source.rs index ec2dd7724..d01147401 100644 --- a/crates/sargon/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source.rs +++ b/crates/sargon/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source.rs @@ -46,7 +46,7 @@ impl IsFactorSource for DeviceFactorSource { FactorSourceKind::Device } } -impl BaseIsFactorSource for DeviceFactorSource { +impl BaseBaseIsFactorSource for DeviceFactorSource { fn common_properties(&self) -> FactorSourceCommon { self.common.clone() } @@ -62,6 +62,10 @@ impl BaseIsFactorSource for DeviceFactorSource { fn set_common_properties(&mut self, updated: FactorSourceCommon) { self.common = updated } + + fn name(&self) -> String { + self.hint.label.clone() + } } impl DeviceFactorSource { @@ -310,4 +314,9 @@ mod tests { BIP39WordCount::TwentyFour ); } + + #[test] + fn name() { + assert_eq!(SUT::sample().name(), "My Phone"); + } } diff --git a/crates/sargon/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source_hint.rs b/crates/sargon/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source_hint.rs index 08971bff7..62a095b25 100644 --- a/crates/sargon/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source_hint.rs +++ b/crates/sargon/src/profile/v100/factors/factor_sources/device_factor_source/device_factor_source_hint.rs @@ -13,10 +13,22 @@ use crate::prelude::*; derive_more::Display, )] #[serde(rename_all = "camelCase")] -#[display("{name} {model}")] +#[display("{label} {device_name} {model}")] pub struct DeviceFactorSourceHint { - /// "iPhone RED" - pub name: String, + /// A user-assigned name for the device, intended to help users + /// differentiate between multiple devices. + /// + /// Example: "My Phone" + #[serde(default = "label_default")] + pub label: String, + + /// The name of the device as provided by the system. + /// + /// To maintain compatibility, this field is still serialized as `name` + /// + /// Example: "iPhone RED" + #[serde(rename = "name")] + pub device_name: String, /// "iPhone SE 2nd gen" pub model: String, @@ -56,7 +68,8 @@ impl DeviceFactorSourceHint { /// Instantiates a new DeviceFactorSourceHint from the specified name, model, /// system version, app version and mnemonic word count. pub fn new( - name: impl AsRef, + label: impl AsRef, + device_name: impl AsRef, model: impl AsRef, system_version: impl Into>, host_app_version: impl Into>, @@ -64,7 +77,8 @@ impl DeviceFactorSourceHint { word_count: BIP39WordCount, ) -> Self { Self { - name: name.as_ref().to_owned(), + label: label.as_ref().to_owned(), + device_name: device_name.as_ref().to_owned(), model: model.as_ref().to_owned(), system_version: system_version.into(), host_app_version: host_app_version.into(), @@ -76,6 +90,7 @@ impl DeviceFactorSourceHint { pub fn with_info(host_info: &HostInfo, word_count: BIP39WordCount) -> Self { let description = host_info.description.clone(); Self::new( + label_default(), description.name, description.model, host_info.host_os.version(), @@ -90,7 +105,8 @@ impl HasSampleValues for DeviceFactorSourceHint { /// A sample used to facilitate unit tests. fn sample() -> Self { Self::new( - "Unknown Name", + "New Phone", + "Unknown Device Name", "iPhone", None, None, @@ -101,6 +117,7 @@ impl HasSampleValues for DeviceFactorSourceHint { fn sample_other() -> Self { Self::new( + "Old Phone", "Android", "Samsung Galaxy S23 Ultra", None, @@ -115,7 +132,8 @@ impl DeviceFactorSourceHint { /// A sample used to facilitate unit tests. pub fn sample_iphone_unknown() -> Self { Self::new( - "Unknown Name", + "Unknown Phone", + "Unknown Device Name", "iPhone", None, None, @@ -125,6 +143,10 @@ impl DeviceFactorSourceHint { } } +fn label_default() -> String { + "My Phone".to_owned() +} + #[cfg(test)] mod tests { @@ -159,7 +181,8 @@ mod tests { &model, r#" { - "name": "Unknown Name", + "label": "Unknown Phone", + "name": "Unknown Device Name", "model": "iPhone", "mnemonicWordCount": 24 } @@ -170,6 +193,7 @@ mod tests { #[test] fn json_app_version_and_system_version_set() { let sut = SUT::new( + "New Phone", "My precious", "iPhone 15 Pro", "17.4.1".to_owned(), @@ -181,6 +205,7 @@ mod tests { &sut, r#" { + "label": "New Phone", "name": "My precious", "model": "iPhone 15 Pro", "systemVersion": "17.4.1", diff --git a/crates/sargon/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_factor_source.rs b/crates/sargon/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_factor_source.rs index a90817db2..dad02912b 100644 --- a/crates/sargon/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_factor_source.rs +++ b/crates/sargon/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_factor_source.rs @@ -82,7 +82,7 @@ impl IsFactorSource for LedgerHardwareWalletFactorSource { FactorSourceKind::LedgerHQHardwareWallet } } -impl BaseIsFactorSource for LedgerHardwareWalletFactorSource { +impl BaseBaseIsFactorSource for LedgerHardwareWalletFactorSource { fn common_properties(&self) -> FactorSourceCommon { self.common.clone() } @@ -98,6 +98,10 @@ impl BaseIsFactorSource for LedgerHardwareWalletFactorSource { fn set_common_properties(&mut self, updated: FactorSourceCommon) { self.common = updated } + + fn name(&self) -> String { + self.hint.label.clone() + } } #[cfg(test)] @@ -178,4 +182,9 @@ mod tests { fn factor_source_kind() { assert_eq!(SUT::sample().factor_source_kind(), SUT::sample().id.kind); } + + #[test] + fn name() { + assert_eq!(SUT::sample().name(), "Orange, scratched"); + } } diff --git a/crates/sargon/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_hint.rs b/crates/sargon/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_hint.rs index 7a0a015b6..5b37e321d 100644 --- a/crates/sargon/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_hint.rs +++ b/crates/sargon/src/profile/v100/factors/factor_sources/ledger_hardware_wallet_factor_source/ledger_hardware_wallet_hint.rs @@ -10,19 +10,25 @@ use crate::prelude::*; Hash, derive_more::Display, )] -#[display("{name} {model}")] +#[display("{label} {model}")] pub struct LedgerHardwareWalletHint { - /// "Orange, scratched" - pub name: String, + /// A user-assigned name for the ledger, intended to help users + /// differentiate between multiple ledgers. + /// + /// To maintain compatibility, this field is still serialized as `name` + /// + /// E.g. "Orange, scratched" + #[serde(rename = "name")] + pub label: String, /// E.g. `nanoS+` pub model: LedgerHardwareWalletModel, } impl LedgerHardwareWalletHint { - pub fn new(name: &str, model: LedgerHardwareWalletModel) -> Self { + pub fn new(label: &str, model: LedgerHardwareWalletModel) -> Self { Self { - name: name.to_string(), + label: label.to_string(), model, } } diff --git a/crates/sargon/src/profile/v100/factors/is_factor_source.rs b/crates/sargon/src/profile/v100/factors/is_factor_source.rs index b1ee33228..79f6218ce 100644 --- a/crates/sargon/src/profile/v100/factors/is_factor_source.rs +++ b/crates/sargon/src/profile/v100/factors/is_factor_source.rs @@ -1,8 +1,6 @@ use crate::prelude::*; -pub trait BaseIsFactorSource: - Into + TryFrom + Clone -{ +pub trait BaseBaseIsFactorSource { fn factor_source_kind(&self) -> FactorSourceKind; fn factor_source_id(&self) -> FactorSourceID; @@ -19,6 +17,22 @@ pub trait BaseIsFactorSource: fn supports_olympia(&self) -> bool { self.common_properties().supports_olympia() } + + fn name(&self) -> String; +} + +pub trait BaseIsFactorSource: + BaseBaseIsFactorSource + Into + TryFrom + Clone +{ +} + +impl< + T: BaseBaseIsFactorSource + + Into + + TryFrom + + Clone, + > BaseIsFactorSource for T +{ } pub trait IsFactorSource: BaseIsFactorSource { diff --git a/crates/sargon/src/signing/collector/signatures_collector.rs b/crates/sargon/src/signing/collector/signatures_collector.rs index 1de8c557c..88dd49125 100644 --- a/crates/sargon/src/signing/collector/signatures_collector.rs +++ b/crates/sargon/src/signing/collector/signatures_collector.rs @@ -533,7 +533,7 @@ mod tests { IndexSet::::from_iter([ FactorSourceKind::LedgerHQHardwareWallet, FactorSourceKind::ArculusCard, - FactorSourceKind::Passphrase, + FactorSourceKind::Password, FactorSourceKind::SecurityQuestions, FactorSourceKind::OffDeviceMnemonic, FactorSourceKind::Device, @@ -1036,7 +1036,7 @@ mod tests { signed_factor_source_kinds: IndexSet::::from_iter([ FactorSourceKind::ArculusCard, - FactorSourceKind::Passphrase, + FactorSourceKind::Password, ]), expected_neglected_factor_source_count: 1, }, @@ -1335,7 +1335,7 @@ mod tests { IndexSet::::from_iter([ FactorSourceKind::LedgerHQHardwareWallet, FactorSourceKind::ArculusCard, - FactorSourceKind::Passphrase, + FactorSourceKind::Password, ]), expected_neglected_factor_source_count: 0, }, @@ -1351,7 +1351,7 @@ mod tests { signed_factor_source_kinds: IndexSet::::from_iter([ FactorSourceKind::ArculusCard, - FactorSourceKind::Passphrase, + FactorSourceKind::Password, FactorSourceKind::Device, ]), expected_neglected_factor_source_count: 2, diff --git a/crates/sargon/src/system/sargon_os/sargon_os_factors.rs b/crates/sargon/src/system/sargon_os/sargon_os_factors.rs index 58893359e..a8327e20f 100644 --- a/crates/sargon/src/system/sargon_os/sargon_os_factors.rs +++ b/crates/sargon/src/system/sargon_os/sargon_os_factors.rs @@ -842,8 +842,8 @@ mod tests { .unwrap(); // ACT - let new_name = "new important name"; - factor.hint.name = new_name.to_owned(); + let new_label = "new important name"; + factor.hint.label = new_label.to_owned(); os.with_timeout(|x| x.update_factor_source(factor.clone().into())) .await .unwrap(); @@ -852,7 +852,7 @@ mod tests { assert!(os.profile().unwrap().factor_sources.into_iter().any(|f| { match f { FactorSource::ArculusCard { value } => { - value.hint.name == *new_name + value.hint.label == *new_label } _ => false, } diff --git a/crates/sargon/src/types/samples/factor_source_ids_with_samples.rs b/crates/sargon/src/types/samples/factor_source_ids_with_samples.rs index 9ab75812e..d5c4b482c 100644 --- a/crates/sargon/src/types/samples/factor_source_ids_with_samples.rs +++ b/crates/sargon/src/types/samples/factor_source_ids_with_samples.rs @@ -9,8 +9,8 @@ pub(crate) static ALL_FACTOR_SOURCE_ID_SAMPLES: Lazy< FactorSourceIDFromHash::sample_ledger_other(), FactorSourceIDFromHash::sample_arculus(), FactorSourceIDFromHash::sample_arculus_other(), - FactorSourceIDFromHash::sample_passphrase(), - FactorSourceIDFromHash::sample_passphrase_other(), + FactorSourceIDFromHash::sample_password(), + FactorSourceIDFromHash::sample_password_other(), FactorSourceIDFromHash::sample_off_device(), FactorSourceIDFromHash::sample_off_device_other(), FactorSourceIDFromHash::sample_security_questions(), @@ -44,12 +44,12 @@ pub(crate) static MNEMONIC_BY_ID_MAP: Lazy< MnemonicWithPassphrase::sample_arculus_other(), ), ( - FactorSourceIDFromHash::sample_passphrase(), - MnemonicWithPassphrase::sample_passphrase(), + FactorSourceIDFromHash::sample_password(), + MnemonicWithPassphrase::sample_password(), ), ( - FactorSourceIDFromHash::sample_passphrase_other(), - MnemonicWithPassphrase::sample_passphrase_other(), + FactorSourceIDFromHash::sample_password_other(), + MnemonicWithPassphrase::sample_password_other(), ), ( FactorSourceIDFromHash::sample_off_device(), diff --git a/crates/sargon/src/types/samples/factor_source_samples.rs b/crates/sargon/src/types/samples/factor_source_samples.rs index 6ac8b2952..7c87a765f 100644 --- a/crates/sargon/src/types/samples/factor_source_samples.rs +++ b/crates/sargon/src/types/samples/factor_source_samples.rs @@ -42,9 +42,13 @@ impl FactorSource { ), ) .into(), - FactorSourceKind::Passphrase => { - PassphraseFactorSource::new(*id).into() - } + FactorSourceKind::Password => PasswordFactorSource::new( + *id, + PasswordFactorSourceHint::new( + format!("Password @ {}", id.body.to_hex()).as_str(), + ), + ) + .into(), FactorSourceKind::SecurityQuestions => { let sealed_mnemonic = SecurityQuestionsSealed_NOT_PRODUCTION_READY_Mnemonic::new_by_encrypting( id.sample_associated_mnemonic().mnemonic, @@ -76,6 +80,7 @@ impl FactorSource { *id, FactorSourceCommon::sample(), DeviceFactorSourceHint::new( + format!("Device Label @ {}", id.body.to_hex()), format!("Device Name @ {}", id.body.to_hex()), format!("Device Model @ {}", id.body.to_hex()), None, diff --git a/examples/iOS/Backend/Sources/Planbok/Dependencies/FactorSourcesClient.swift b/examples/iOS/Backend/Sources/Planbok/Dependencies/FactorSourcesClient.swift index f3f41c057..d211c9acd 100644 --- a/examples/iOS/Backend/Sources/Planbok/Dependencies/FactorSourcesClient.swift +++ b/examples/iOS/Backend/Sources/Planbok/Dependencies/FactorSourcesClient.swift @@ -37,7 +37,7 @@ extension FactorSourcesClient: DependencyKey { LedgerHardwareWalletFactorSource( mnemonicWithPassphrase: mnemonicWithPassphrase, hint: LedgerHardwareWalletHint( - name: "Unknown", + label: "Unknown", model: .nanoSPlus ), common: FactorSourceCommon.babylon() @@ -47,13 +47,13 @@ extension FactorSourcesClient: DependencyKey { OffDeviceMnemonicFactorSource( mnemonicWithPassphrase: mnemonicWithPassphrase, hint: .init( - displayName: "Unknown" + label: "Unknown" ) ).asGeneral case .arculusCard: ArculusCardFactorSource( mnemonicWithPassphrase: mnemonicWithPassphrase, - name: "Unknown" + label: "Unknown" ).asGeneral case .securityQuestions: fatalError( diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSource.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSource.kt index 7c277fce7..e02aae0f6 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSource.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSource.kt @@ -9,12 +9,13 @@ import com.radixdlt.sargon.HostInfo import com.radixdlt.sargon.LedgerHardwareWalletFactorSource import com.radixdlt.sargon.MnemonicWithPassphrase import com.radixdlt.sargon.OffDeviceMnemonicFactorSource -import com.radixdlt.sargon.PassphraseFactorSource +import com.radixdlt.sargon.PasswordFactorSource import com.radixdlt.sargon.SecurityQuestionsNotProductionReadyFactorSource import com.radixdlt.sargon.TrustedContactFactorSource import com.radixdlt.sargon.deviceFactorSourceIsMainBdfs import com.radixdlt.sargon.factorSourceSupportsBabylon import com.radixdlt.sargon.factorSourceSupportsOlympia +import com.radixdlt.sargon.factorSourceName import com.radixdlt.sargon.newDeviceFactorSourceBabylon import com.radixdlt.sargon.newDeviceFactorSourceOlympia @@ -26,7 +27,7 @@ val FactorSource.id: FactorSourceId is FactorSource.OffDeviceMnemonic -> value.id.asGeneral() is FactorSource.SecurityQuestions -> value.id.asGeneral() is FactorSource.TrustedContact -> value.id.asGeneral() - is FactorSource.Passphrase -> value.id.asGeneral() + is FactorSource.Password -> value.id.asGeneral() } val FactorSource.kind: FactorSourceKind @@ -37,7 +38,7 @@ val FactorSource.kind: FactorSourceKind is FactorSource.OffDeviceMnemonic -> value.kind is FactorSource.SecurityQuestions -> value.kind is FactorSource.TrustedContact -> value.kind - is FactorSource.Passphrase -> value.kind + is FactorSource.Password -> value.kind } fun DeviceFactorSource.asGeneral() = FactorSource.Device(value = this) @@ -75,6 +76,9 @@ val FactorSource.supportsOlympia: Boolean val FactorSource.supportsBabylon: Boolean get() = factorSourceSupportsBabylon(factorSource = this) +val FactorSource.name: String + get() = factorSourceName(factorSource = this) + val DeviceFactorSource.kind: FactorSourceKind get() = FactorSourceKind.DEVICE @@ -93,6 +97,6 @@ val SecurityQuestionsNotProductionReadyFactorSource.kind: FactorSourceKind val TrustedContactFactorSource.kind: FactorSourceKind get() = FactorSourceKind.TRUSTED_CONTACT -val PassphraseFactorSource.kind: FactorSourceKind - get() = FactorSourceKind.PASSPHRASE +val PasswordFactorSource.kind: FactorSourceKind + get() = FactorSourceKind.PASSWORD diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/FactorSourceTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/FactorSourceTest.kt index 60a7d7565..cfe9bebfc 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/FactorSourceTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/FactorSourceTest.kt @@ -9,6 +9,7 @@ import com.radixdlt.sargon.extensions.kind import com.radixdlt.sargon.extensions.olympia import com.radixdlt.sargon.extensions.supportsBabylon import com.radixdlt.sargon.extensions.supportsOlympia +import com.radixdlt.sargon.extensions.name import com.radixdlt.sargon.samples.Sample import com.radixdlt.sargon.samples.sample import com.radixdlt.sargon.samples.sampleMainnet @@ -135,6 +136,14 @@ class FactorSourceTest : SampleTestable { ) } + @Test + fun testName() { + assertEquals( + "My Phone", + FactorSource.sample().name + ) + } + @Test fun testNewBabylonIsMain() { assertTrue( @@ -215,7 +224,7 @@ class FactorSourceTest : SampleTestable { flags = emptyList() ), hint = ArculusCardHint( - name = "My Arculus", + label = "My Arculus", model = ArculusCardModel.ARCULUS_COLD_STORAGE_WALLET ) ) @@ -237,7 +246,7 @@ class FactorSourceTest : SampleTestable { flags = emptyList() ), hint = OffDeviceMnemonicHint( - displayName = DisplayName("My mnemonic stored somewhere") + label = DisplayName("My mnemonic stored somewhere") ) ) )