TM-SGNL-iOS/SignalServiceKit/Messages/RecipientHidingManager+SignalServiceAddress.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

123 lines
4.8 KiB
Swift

//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
/// These extensions allow callers to use RecipientHidingManager
/// via SignalServiceAddress, temporarily, while we still have
/// callsites using SignalServiceAddress.
/// The actual root identifier used by RecipientHidingManager is
/// SignalRecipient (well, its row id), and all these methods just do
/// a lookup of SignalRecipient by address.
/// Eventually, all callsites should be explicit about the recipient
/// identifier they have (whether a SignalRecipient or some as
/// yet undefined combo of {ACI} or {e164 + PNI}.
/// At that point, this extension should be deleted.
extension RecipientHidingManager {
// MARK: Read
/// Returns set of ``SignalServiceAddress``es corresponding with
/// all hidden recipients.
///
/// - Parameter tx: The transaction to use for database operations.
public func hiddenAddresses(tx: DBReadTransaction) -> Set<SignalServiceAddress> {
return Set(hiddenRecipients(tx: tx).compactMap { (recipient: SignalRecipient) -> SignalServiceAddress? in
let address = recipient.address
guard address.isValid else { return nil }
return address
})
}
/// Whether a service address corresponds with a hidden recipient.
///
/// - Parameter address: The service address corresponding with
/// the ``SignalRecipient``.
/// - Parameter tx: The transaction to use for database operations.
///
/// - Returns: True if the address is hidden.
public func isHiddenAddress(_ address: SignalServiceAddress, tx: DBReadTransaction) -> Bool {
guard
let localAddress = DependenciesBridge.shared.tsAccountManager.localIdentifiers(tx: tx)?.aciAddress,
!localAddress.isEqualToAddress(address) else
{
return false
}
guard let recipient = recipient(from: address, tx: tx) else {
return false
}
return isHiddenRecipient(recipient, tx: tx)
}
// MARK: Write
/// Inserts hidden-recipient state for the given `SignalServiceAddress`.
///
/// - Parameter inKnownMessageRequestState
/// Whether we know immediately that this hidden recipient's chat should be
/// in a message-request state.
/// - Parameter wasLocallyInitiated: Whether the user initiated
/// the hide on this device (true) or a linked device (false).
public func addHiddenRecipient(
_ address: SignalServiceAddress,
inKnownMessageRequestState: Bool,
wasLocallyInitiated: Bool,
tx: DBWriteTransaction
) throws {
guard address.isValid else {
throw RecipientHidingError.invalidRecipientAddress(address)
}
guard
let localAddress = DependenciesBridge.shared.tsAccountManager.localIdentifiers(tx: tx)?.aciAddress,
!localAddress.isEqualToAddress(address)
else {
throw RecipientHidingError.cannotHideLocalAddress
}
let recipient = OWSAccountIdFinder.ensureRecipient(
forAddress: address,
transaction: SDSDB.shimOnlyBridge(tx)
)
try addHiddenRecipient(
recipient,
inKnownMessageRequestState: inKnownMessageRequestState,
wasLocallyInitiated: wasLocallyInitiated,
tx: tx
)
}
/// Removes a recipient from the hidden recipient table.
///
/// - Parameter address: The service address corresponding with
/// the ``SignalRecipient``.
/// - Parameter wasLocallyInitiated: Whether the user initiated
/// the hide on this device (true) or a linked device (false).
/// - Parameter tx: The transaction to use for database operations.
public func removeHiddenRecipient(
_ address: SignalServiceAddress,
wasLocallyInitiated: Bool,
tx: DBWriteTransaction
) throws {
guard
let localAddress = DependenciesBridge.shared.tsAccountManager.localIdentifiers(tx: tx)?.aciAddress,
!localAddress.isEqualToAddress(address)
else {
owsFailDebug("Cannot unhide the local address")
return
}
if let recipient = recipient(from: address, tx: tx) {
try removeHiddenRecipient(recipient, wasLocallyInitiated: wasLocallyInitiated, tx: tx)
}
}
/// Returns the id for a recipient, if the recipient exists.
///
/// - Parameter address: The service address corresponding with
/// the ``SignalRecipient``.
/// - Parameter tx: The transaction to use for database operations.
///
/// - Returns: The ``SignalRecipient``.
private func recipient(from address: SignalServiceAddress, tx: DBReadTransaction) -> SignalRecipient? {
return DependenciesBridge.shared.recipientDatabaseTable
.fetchRecipient(address: address, tx: tx)
}
}