Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/SignalServiceKit/Usernames/UsernameApiClient.swift
1 views
//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

public import LibSignalClient

/// Manages usernames-related API calls.
public protocol UsernameApiClient {

    // MARK: Selection

    /// Reserves one of the given username candidates.
    ///
    /// - Parameter usernameCandidates
    /// Candidate usernames to reserve.
    /// - Parameter attemptId
    /// An ID for this attempt, to later disambiguate between multiple
    /// potentially-overlapping attempts.
    func reserveUsernameCandidates(
        usernameCandidates: Usernames.HashedUsername.GeneratedCandidates,
    ) async throws -> Usernames.ApiClientReservationResult

    /// Confirms the given username, which must have previously been reserved.
    ///
    /// - Parameter encryptedUsernameForLink
    /// An encrypted form of this username for use in a username link.
    func confirmReservedUsername(
        reservedUsername: Usernames.HashedUsername,
        encryptedUsernameForLink: Data,
        chatServiceAuth: ChatServiceAuth,
    ) async throws -> Usernames.ApiClientConfirmationResult

    // MARK: Deletion

    /// Delete the username and username link for the current user.
    func deleteCurrentUsername() async throws

    // MARK: Lookup

    /// Looks up the ACI corresponding to the given username, if one exists.
    func lookupAci(
        forHashedUsername hashedUsername: Usernames.HashedUsername,
    ) async throws -> Aci?

    // MARK: Links

    /// Set the encrypted username for the local user's username link.
    ///
    /// - SeeAlso
    /// ``Usernames.UsernameLink`` and ``UsernameLinkManager``.
    ///
    /// - Parameter encryptedUsername
    /// The new encrypted username for the username link.
    /// - Parameter keepLinkHandle
    /// Whether we should ask the service to keep the existing link handle the
    /// same, rather than rotating it. Intended for use specifically in
    /// ``LocalUsernameManager/updateVisibleCaseOfExistingUsername``.
    /// - Returns
    /// The handle for the local user's encrypted username.
    func setUsernameLink(
        encryptedUsername: Data,
        keepLinkHandle: Bool,
    ) async throws -> UUID

    /// Gets and decrypts the username for the given handle and entropy, if any.
    ///
    /// - SeeAlso
    /// ``Usernames.UsernameLink`` and ``UsernameLinkManager``.
    func getUsernameLink(handle: UUID, entropy: Data) async throws -> LibSignalClient.Username?
}

public extension Usernames {
    enum ApiClientReservationResult {
        case successful(
            username: Usernames.ParsedUsername,
            hashedUsername: Usernames.HashedUsername,
        )
        case rejected
        case rateLimited
    }

    enum ApiClientConfirmationResult {
        /// The reservation was successfully confirmed.
        case success(usernameLinkHandle: UUID)
        /// The reservation was rejected. This may be because we no longer hold
        /// the reservation, the reservation lapsed, or something about the
        /// reservation was invalid.
        case rejected
        /// The reservation failed because we have been rate-limited.
        case rateLimited
    }
}