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

import Foundation

public extension OWSRequestFactory {
    private enum UsernameApiPaths {
        static let reserveUsername = "v1/accounts/username_hash/reserve"
        static let confirmReservedUsername = "v1/accounts/username_hash/confirm"
        static let deleteUsername = "v1/accounts/username_hash"
        static func aciLookup(forUsernameHash usernameHash: String) -> String {
            "v1/accounts/username_hash/\(usernameHash)"
        }

        static let setUsernameLink = "v1/accounts/username_link"
    }

    /// Attempt to reserve one of the given username hashes. If successful,
    /// will return the reserved hash.
    ///
    /// A successful reservation is valid for 5 minutes.
    static func reserveUsernameRequest(
        usernameHashes: [String],
    ) -> TSRequest {
        let url = URL(string: UsernameApiPaths.reserveUsername)!
        let params: [String: Any] = [
            "usernameHashes": usernameHashes,
        ]

        return TSRequest(
            url: url,
            method: HTTPMethod.put.methodName,
            parameters: params,
        )
    }

    /// Confirm a previously-reserved username hash.
    ///
    /// - Parameter reservedUsernameHash
    /// The hash string from a hashed username returned by a prior call to
    /// reserve a desired nickname.
    /// - Parameter reservedUsernameZKProof
    /// The zkproof string from a hashed username returned by a prior call to
    /// reserve a desired nickname.
    /// - Parameter encryptedUsernameForLink
    /// An encrypted form of the reserved username to be used in a username
    /// link.
    static func confirmReservedUsernameRequest(
        reservedUsernameHash hashString: String,
        reservedUsernameZKProof proofString: String,
        encryptedUsernameForLink: Data,
    ) -> TSRequest {
        let url = URL(string: UsernameApiPaths.confirmReservedUsername)!
        let params: [String: String] = [
            "usernameHash": hashString,
            "zkProof": proofString,
            "encryptedUsername": encryptedUsernameForLink.asBase64Url,
        ]

        return TSRequest(
            url: url,
            method: HTTPMethod.put.methodName,
            parameters: params,
        )
    }

    /// Delete the user's server-stored username hash.
    static func deleteExistingUsernameRequest() -> TSRequest {
        let url = URL(string: UsernameApiPaths.deleteUsername)!

        return TSRequest(
            url: url,
            method: HTTPMethod.delete.methodName,
            parameters: nil,
        )
    }

    /// Look up the ACI for the given username hash.
    static func lookupAciUsernameRequest(
        usernameHashToLookup usernameHash: String,
    ) -> TSRequest {
        let url = URL(string: UsernameApiPaths.aciLookup(
            forUsernameHash: usernameHash,
        ))!

        var request = TSRequest(
            url: url,
            method: HTTPMethod.get.methodName,
            parameters: nil,
        )

        request.auth = .anonymous

        return request
    }

    /// Store the given encrypted username for use in the authenticated user's
    /// username link. Optionally requests that the service not rotate the
    /// handle for this username link.
    ///
    /// - SeeAlso
    /// ``Usernames.UsernameLink`` and ``UsernameLinkManager``.
    static func setUsernameLinkRequest(
        encryptedUsername: Data,
        keepLinkHandle: Bool,
    ) -> TSRequest {
        let url = URL(string: UsernameApiPaths.setUsernameLink)!
        let params: [String: Any] = [
            "usernameLinkEncryptedValue": encryptedUsername.asBase64Url,
            "keepLinkHandle": keepLinkHandle,
        ]

        let request = TSRequest(
            url: url,
            method: HTTPMethod.put.methodName,
            parameters: params,
        )

        return request
    }
}