mirror of
https://github.com/bitwarden/ios.git
synced 2025-12-10 00:42:29 -06:00
[BITAU-121] Add accountDomain and accountEmail to AuthenticatorBridge items (#1017)
This commit is contained in:
parent
621d9019be
commit
0e113bf7cb
@ -6,6 +6,12 @@ import Foundation
|
||||
public struct AuthenticatorBridgeItemDataModel: Codable, Equatable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The domain of the Bitwarden account that owns this item. (e.g. https://vault.bitwarden.com)
|
||||
public let accountDomain: String?
|
||||
|
||||
/// The email of the Bitwarden account that owns this item.
|
||||
public let accountEmail: String?
|
||||
|
||||
/// Bool indicating if this item is a favorite.
|
||||
public let favorite: Bool
|
||||
|
||||
@ -18,6 +24,6 @@ public struct AuthenticatorBridgeItemDataModel: Codable, Equatable {
|
||||
/// The TOTP key used to generate codes.
|
||||
public let totpKey: String?
|
||||
|
||||
/// The username of the Bitwarden account that owns this iteam.
|
||||
/// The username of the item.
|
||||
public let username: String?
|
||||
}
|
||||
|
||||
@ -6,6 +6,12 @@ import Foundation
|
||||
public struct AuthenticatorBridgeItemDataView: Codable, Equatable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The domain of the Bitwarden account that owns this item. (e.g. https://vault.bitwarden.com)
|
||||
public let accountDomain: String?
|
||||
|
||||
/// The email of the Bitwarden account that owns this item.
|
||||
public let accountEmail: String?
|
||||
|
||||
/// Bool indicating if this item is a favorite.
|
||||
public let favorite: Bool
|
||||
|
||||
@ -18,19 +24,29 @@ public struct AuthenticatorBridgeItemDataView: Codable, Equatable {
|
||||
/// The TOTP key used to generate codes.
|
||||
public let totpKey: String?
|
||||
|
||||
/// The username of the Bitwarden account that owns this iteam.
|
||||
/// The username of the item.
|
||||
public let username: String?
|
||||
|
||||
/// Initialize an `AuthenticatorBridgeItemDataView` with the values provided.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - accountDomain: The domain of the Bitwarden account that owns this item.
|
||||
/// - accountEmail: The email of the Bitwarden account that owns this item
|
||||
/// - favorite: Bool indicating if this item is a favorite.
|
||||
/// - id: The unique id of the item.
|
||||
/// - name: The name of the item.
|
||||
/// - totpKey: The TOTP key used to generate codes.
|
||||
/// - username: The username of the Bitwarden account that owns this item.
|
||||
/// - username: The username of the item.
|
||||
///
|
||||
public init(favorite: Bool, id: String, name: String, totpKey: String?, username: String?) {
|
||||
public init(accountDomain: String?,
|
||||
accountEmail: String?,
|
||||
favorite: Bool,
|
||||
id: String,
|
||||
name: String,
|
||||
totpKey: String?,
|
||||
username: String?) {
|
||||
self.accountDomain = accountDomain
|
||||
self.accountEmail = accountEmail
|
||||
self.favorite = favorite
|
||||
self.id = id
|
||||
self.name = name
|
||||
|
||||
@ -62,6 +62,8 @@ public class DefaultAuthenticatorCryptographyService: SharedCryptographyService
|
||||
|
||||
return items.map { item in
|
||||
AuthenticatorBridgeItemDataView(
|
||||
accountDomain: (try? decrypt(item.accountDomain, withKey: symmetricKey)) ?? "",
|
||||
accountEmail: (try? decrypt(item.accountEmail, withKey: symmetricKey)) ?? "",
|
||||
favorite: item.favorite,
|
||||
id: item.id,
|
||||
name: (try? decrypt(item.name, withKey: symmetricKey)) ?? "",
|
||||
@ -79,6 +81,8 @@ public class DefaultAuthenticatorCryptographyService: SharedCryptographyService
|
||||
|
||||
return items.map { item in
|
||||
AuthenticatorBridgeItemDataModel(
|
||||
accountDomain: encrypt(item.accountDomain, withKey: symmetricKey) ?? "",
|
||||
accountEmail: encrypt(item.accountEmail, withKey: symmetricKey) ?? "",
|
||||
favorite: item.favorite,
|
||||
id: item.id,
|
||||
name: encrypt(item.name, withKey: symmetricKey) ?? "",
|
||||
|
||||
@ -49,7 +49,13 @@ final class AuthenticatorBridgeItemDataTests: AuthenticatorBridgeKitTestCase {
|
||||
context: dataStore.persistentContainer.viewContext,
|
||||
userId: "userId",
|
||||
authenticatorItem: AuthenticatorBridgeItemDataModel(
|
||||
favorite: true, id: "is", name: "name", totpKey: "TOTP Key", username: "username"
|
||||
accountDomain: "https://vault.example.com",
|
||||
accountEmail: "test@example.com",
|
||||
favorite: true,
|
||||
id: "is",
|
||||
name: "name",
|
||||
totpKey: "TOTP Key",
|
||||
username: "username"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -71,6 +71,16 @@ final class SharedCryptographyServiceTests: AuthenticatorBridgeKitTestCase {
|
||||
|
||||
// Encrypted values should not remain equal, unless they were `nil`
|
||||
XCTAssertNotEqual(item.name, encryptedItem.name)
|
||||
if item.accountDomain != nil {
|
||||
XCTAssertNotEqual(item.accountDomain, encryptedItem.accountDomain)
|
||||
} else {
|
||||
XCTAssertNil(encryptedItem.accountDomain)
|
||||
}
|
||||
if item.accountEmail != nil {
|
||||
XCTAssertNotEqual(item.accountEmail, encryptedItem.accountEmail)
|
||||
} else {
|
||||
XCTAssertNil(encryptedItem.accountEmail)
|
||||
}
|
||||
if item.totpKey != nil {
|
||||
XCTAssertNotEqual(item.totpKey, encryptedItem.totpKey)
|
||||
} else {
|
||||
|
||||
@ -4,6 +4,8 @@ import Foundation
|
||||
|
||||
extension AuthenticatorBridgeItemDataView {
|
||||
static func fixture(
|
||||
accountDomain: String? = "",
|
||||
accountEmail: String? = "",
|
||||
favorite: Bool = false,
|
||||
id: String = UUID().uuidString,
|
||||
name: String = "Name",
|
||||
@ -11,6 +13,8 @@ extension AuthenticatorBridgeItemDataView {
|
||||
username: String? = nil
|
||||
) -> AuthenticatorBridgeItemDataView {
|
||||
AuthenticatorBridgeItemDataView(
|
||||
accountDomain: accountDomain,
|
||||
accountEmail: accountEmail,
|
||||
favorite: favorite,
|
||||
id: id,
|
||||
name: name,
|
||||
@ -23,9 +27,12 @@ extension AuthenticatorBridgeItemDataView {
|
||||
[
|
||||
AuthenticatorBridgeItemDataView.fixture(),
|
||||
AuthenticatorBridgeItemDataView.fixture(favorite: true),
|
||||
AuthenticatorBridgeItemDataView.fixture(accountDomain: "https://vault.example.com"),
|
||||
AuthenticatorBridgeItemDataView.fixture(accountEmail: "bw@example.com"),
|
||||
AuthenticatorBridgeItemDataView.fixture(totpKey: "TOTP Key"),
|
||||
AuthenticatorBridgeItemDataView.fixture(username: "Username"),
|
||||
AuthenticatorBridgeItemDataView.fixture(totpKey: "TOTP Key", username: "Username"),
|
||||
AuthenticatorBridgeItemDataView.fixture(accountEmail: ""),
|
||||
AuthenticatorBridgeItemDataView.fixture(totpKey: ""),
|
||||
AuthenticatorBridgeItemDataView.fixture(username: ""),
|
||||
AuthenticatorBridgeItemDataView.fixture(totpKey: "", username: ""),
|
||||
|
||||
@ -7,30 +7,14 @@ class MockSharedCryptographyService: SharedCryptographyService {
|
||||
var decryptCalled = false
|
||||
var encryptCalled = false
|
||||
|
||||
func decryptAuthenticatorItemDatas(
|
||||
_ items: [AuthenticatorBridgeKit.AuthenticatorBridgeItemData]
|
||||
) async throws -> [AuthenticatorBridgeKit.AuthenticatorBridgeItemDataView] {
|
||||
decryptCalled = true
|
||||
|
||||
return items.compactMap { item in
|
||||
guard let model = item.model else { return nil }
|
||||
|
||||
return AuthenticatorBridgeItemDataView(
|
||||
favorite: model.favorite,
|
||||
id: model.id,
|
||||
name: model.name,
|
||||
totpKey: model.totpKey,
|
||||
username: model.username
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func decryptAuthenticatorItems(
|
||||
_ items: [AuthenticatorBridgeItemDataModel]
|
||||
) async throws -> [AuthenticatorBridgeItemDataView] {
|
||||
decryptCalled = true
|
||||
return items.map { model in
|
||||
AuthenticatorBridgeItemDataView(
|
||||
accountDomain: model.accountDomain,
|
||||
accountEmail: model.accountEmail,
|
||||
favorite: model.favorite,
|
||||
id: model.id,
|
||||
name: model.name,
|
||||
@ -46,6 +30,8 @@ class MockSharedCryptographyService: SharedCryptographyService {
|
||||
encryptCalled = true
|
||||
return items.map { view in
|
||||
AuthenticatorBridgeItemDataModel(
|
||||
accountDomain: view.accountDomain,
|
||||
accountEmail: view.accountEmail,
|
||||
favorite: view.favorite,
|
||||
id: view.id,
|
||||
name: view.name,
|
||||
|
||||
@ -160,16 +160,17 @@ actor DefaultAuthenticatorSyncService: NSObject, AuthenticatorSyncService {
|
||||
let decryptedCiphers = try await totpCiphers.asyncMap { cipher in
|
||||
try await self.clientService.vault(for: userId).ciphers().decrypt(cipher: cipher)
|
||||
}
|
||||
let account = try await stateService.getActiveAccount()
|
||||
let username = account.profile.email
|
||||
let account = try? await stateService.getAccount(userId: userId)
|
||||
|
||||
return decryptedCiphers.map { cipher in
|
||||
AuthenticatorBridgeItemDataView(
|
||||
accountDomain: account?.settings.environmentUrls?.webVaultHost,
|
||||
accountEmail: account?.profile.email,
|
||||
favorite: false,
|
||||
id: cipher.id ?? UUID().uuidString,
|
||||
name: cipher.name,
|
||||
totpKey: cipher.login?.totp,
|
||||
username: username
|
||||
username: cipher.login?.username
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -111,7 +111,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
deletedDate: Date(timeIntervalSinceNow: -10000),
|
||||
id: "Deleted",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -134,7 +134,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -163,7 +163,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
cipherDataStore.cipherSubjectByUserId["1"]?.send([
|
||||
.fixture(
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -172,11 +172,13 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
waitFor(authBridgeItemService.storedItems["1"]?.first != nil)
|
||||
|
||||
let item = try XCTUnwrap(authBridgeItemService.storedItems["1"]?.first)
|
||||
XCTAssertEqual(item.accountDomain, "vault.bitwarden.com")
|
||||
XCTAssertEqual(item.accountEmail, "user@bitwarden.com")
|
||||
XCTAssertEqual(item.favorite, false)
|
||||
XCTAssertNotNil(item.id)
|
||||
XCTAssertEqual(item.name, "Bitwarden")
|
||||
XCTAssertEqual(item.totpKey, "totp")
|
||||
XCTAssertEqual(item.username, "user@bitwarden.com")
|
||||
XCTAssertEqual(item.username, "masked@example.com")
|
||||
}
|
||||
|
||||
/// Verifies that the AuthSyncService responds to new Ciphers published by converting them into ItemViews and
|
||||
@ -190,7 +192,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -199,11 +201,13 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
waitFor(authBridgeItemService.storedItems["1"]?.first != nil)
|
||||
|
||||
let item = try XCTUnwrap(authBridgeItemService.storedItems["1"]?.first)
|
||||
XCTAssertEqual(item.accountDomain, "vault.bitwarden.com")
|
||||
XCTAssertEqual(item.accountEmail, "user@bitwarden.com")
|
||||
XCTAssertEqual(item.favorite, false)
|
||||
XCTAssertEqual(item.id, "1234")
|
||||
XCTAssertEqual(item.name, "Bitwarden")
|
||||
XCTAssertEqual(item.totpKey, "totp")
|
||||
XCTAssertEqual(item.username, "user@bitwarden.com")
|
||||
XCTAssertEqual(item.username, "masked@example.com")
|
||||
}
|
||||
|
||||
/// Verifies that the AuthSyncService handles an error when attempting to fetch the accounts to check
|
||||
@ -343,7 +347,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -360,7 +364,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -392,7 +396,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -416,7 +420,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -424,14 +428,18 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
waitFor(authBridgeItemService.storedItems["1"]?.first != nil)
|
||||
|
||||
let item = try XCTUnwrap(authBridgeItemService.storedItems["1"]?.first)
|
||||
XCTAssertEqual(item.accountDomain, "vault.bitwarden.com")
|
||||
XCTAssertEqual(item.accountEmail, "user@bitwarden.com")
|
||||
XCTAssertEqual(item.favorite, false)
|
||||
XCTAssertEqual(item.id, "1234")
|
||||
XCTAssertEqual(item.name, "Bitwarden")
|
||||
XCTAssertEqual(item.totpKey, "totp")
|
||||
XCTAssertEqual(item.username, "user@bitwarden.com")
|
||||
XCTAssertEqual(item.username, "masked@example.com")
|
||||
|
||||
await stateService.addAccount(.fixture(profile: .fixture(email: "different@bitwarden.com",
|
||||
userId: "2")))
|
||||
await stateService.addAccount(.fixture(
|
||||
profile: .fixture(email: "different@bitwarden.com", userId: "2"),
|
||||
settings: .fixture(environmentUrls: .fixture(webVault: URL(string: "https://vault.example.com")))
|
||||
))
|
||||
stateService.syncToAuthenticatorByUserId["2"] = true
|
||||
vaultTimeoutService.isClientLocked["2"] = false
|
||||
stateService.syncToAuthenticatorSubject.send(("2", true))
|
||||
@ -440,7 +448,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "4321",
|
||||
login: .fixture(
|
||||
username: "different@bitwarden.com",
|
||||
username: "masked2@example.com",
|
||||
totp: "totp2"
|
||||
)
|
||||
),
|
||||
@ -448,11 +456,13 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
waitFor(authBridgeItemService.storedItems["2"]?.first != nil)
|
||||
|
||||
let otherItem = try XCTUnwrap(authBridgeItemService.storedItems["2"]?.first)
|
||||
XCTAssertEqual(otherItem.accountDomain, "vault.example.com")
|
||||
XCTAssertEqual(otherItem.accountEmail, "different@bitwarden.com")
|
||||
XCTAssertEqual(otherItem.favorite, false)
|
||||
XCTAssertEqual(otherItem.id, "4321")
|
||||
XCTAssertEqual(otherItem.name, "Bitwarden")
|
||||
XCTAssertEqual(otherItem.totpKey, "totp2")
|
||||
XCTAssertEqual(otherItem.username, "different@bitwarden.com")
|
||||
XCTAssertEqual(otherItem.username, "masked2@example.com")
|
||||
}
|
||||
|
||||
/// When the sync is turned on, but the vault is locked, the service should subscribe and wait
|
||||
@ -473,7 +483,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -482,11 +492,13 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
waitFor(authBridgeItemService.storedItems["1"]?.first != nil)
|
||||
|
||||
let item = try XCTUnwrap(authBridgeItemService.storedItems["1"]?.first)
|
||||
XCTAssertEqual(item.accountDomain, "vault.bitwarden.com")
|
||||
XCTAssertEqual(item.accountEmail, "user@bitwarden.com")
|
||||
XCTAssertEqual(item.favorite, false)
|
||||
XCTAssertEqual(item.id, "1234")
|
||||
XCTAssertEqual(item.name, "Bitwarden")
|
||||
XCTAssertEqual(item.totpKey, "totp")
|
||||
XCTAssertEqual(item.username, "user@bitwarden.com")
|
||||
XCTAssertEqual(item.username, "masked@example.com")
|
||||
}
|
||||
|
||||
/// Verifies that the AuthSyncService stops listening for Cipher updates when the user's vault is locked.
|
||||
@ -508,7 +520,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -545,7 +557,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
@ -585,7 +597,7 @@ final class AuthenticatorSyncServiceTests: BitwardenTestCase { // swiftlint:disa
|
||||
.fixture(
|
||||
id: "1234",
|
||||
login: .fixture(
|
||||
username: "user@bitwarden.com",
|
||||
username: "masked@example.com",
|
||||
totp: "totp"
|
||||
)
|
||||
),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user