TM-SGNL-iOS/SignalServiceKit/Network/API/Requests/AccountAttributes/AccountAttributes.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

151 lines
6 KiB
Swift

//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
/// Account attributes set on the server via `updatePrimaryDeviceAttributesRequest` request,
/// as well as various registration requests.
public struct AccountAttributes: Codable {
/// All Signal-iOS clients support voice
public let voice: Bool = true
/// All Signal-iOS clients support voice
public let video: Bool = true
/// Devices that don't support push must tell the server they fetch messages manually.
public let isManualMessageFetchEnabled: Bool
/// A randomly generated ID that is associated with the user's ACI that identifies
/// a single registration and is sent to e.g. message recipients. If this changes, it tells
/// you the sender has re-registered, and is cheaper to compare than doing full key comparison.
public let registrationId: UInt32
/// A randomly generated ID that is associated with the user's PNI that identifies
/// a single registration and is sent to e.g. message recipients. If this changes, it tells
/// you the sender has re-registered, and is cheaper to compare than doing full key comparison.
public let pniRegistrationId: UInt32
/// Base64-encoded SMKUDAccessKey generated from the user's profile key.
public let unidentifiedAccessKey: String?
/// Whether the user allows sealed sender messages to come from arbitrary senders.
public let unrestrictedUnidentifiedAccess: Bool
/// Reglock token derived from KBS master key, if reglock is enabled.
/// hexadecimal encoed (e.g. use `Data.hexadecimalString`)
///
/// NOTE: previously, we'd include the pin in this object if the reglock token
/// was not included but a v1 pin was set. This new formal struct is only used with
/// v2-compliant clients, so that is ignored.
public let registrationLockToken: String?
// The user's pin code. For backwards compatibility from before reglock v2.
public let pin: String?
/// Password derived from the KBS master key that the user may be able to use to
/// (re)register without needing to verify an code sent to their phone number.
///
/// Is wiped with some frequency by the server to prevent stale-ness for abandoned
/// accounts, clients should refresh it with some regularity.
/// This happens on every app update, which is at most once every 90 days.
/// base64 encoded (e.g. use `Data.base64EncodedString()`)
public let registrationRecoveryPassword: String?
/// The device name the user entered for a linked device, encrypted with the user's ACI key pair.
/// Unused (nil) on primary device requests.
public let encryptedDeviceName: String?
/// Whether the user has opted to allow their account to be discoverable by phone number.
public let discoverableByPhoneNumber: Bool
public let capabilities: Capabilities
public enum CodingKeys: String, CodingKey {
case voice
case video
case isManualMessageFetchEnabled = "fetchesMessages"
case registrationId
case pniRegistrationId
case unidentifiedAccessKey
case unrestrictedUnidentifiedAccess
case registrationLockToken = "registrationLock"
case pin
case registrationRecoveryPassword = "recoveryPassword"
case encryptedDeviceName = "name"
case discoverableByPhoneNumber
case capabilities
}
public enum TwoFactorAuthMode {
case none
case v1(pinCode: String)
case v2(reglockToken: String)
}
public init(
isManualMessageFetchEnabled: Bool,
registrationId: UInt32,
pniRegistrationId: UInt32,
unidentifiedAccessKey: String?,
unrestrictedUnidentifiedAccess: Bool,
twofaMode: TwoFactorAuthMode,
registrationRecoveryPassword: String?,
encryptedDeviceName: String?,
discoverableByPhoneNumber: PhoneNumberDiscoverability?,
hasSVRBackups: Bool
) {
self.isManualMessageFetchEnabled = isManualMessageFetchEnabled
self.registrationId = registrationId
self.pniRegistrationId = pniRegistrationId
self.unidentifiedAccessKey = unidentifiedAccessKey
self.unrestrictedUnidentifiedAccess = unrestrictedUnidentifiedAccess
switch twofaMode {
case .none:
self.registrationLockToken = nil
self.pin = nil
case .v1(let pinCode):
self.registrationLockToken = nil
self.pin = pinCode
case .v2(let reglockToken):
self.registrationLockToken = reglockToken
self.pin = nil
}
self.registrationRecoveryPassword = registrationRecoveryPassword
self.encryptedDeviceName = encryptedDeviceName
self.discoverableByPhoneNumber = discoverableByPhoneNumber.orAccountAttributeDefault.isDiscoverable
self.capabilities = Capabilities(hasSVRBackups: hasSVRBackups)
}
public struct Capabilities: Codable {
public let transfer = true
public let hasSVRBackups: Bool
public let pni = true
public let paymentActivation = true
public let deleteSyncSendSupport = true
// TODO: remove this once the server removes the capability.
public let versionedExpireTimer = true
public let storageServiceRecordIkm = FeatureFlags.storageServiceRecordIkmMigration
public enum CodingKeys: String, CodingKey {
case transfer
case hasSVRBackups = "storage"
case pni
case paymentActivation
case deleteSyncSendSupport = "deleteSync"
case versionedExpireTimer = "versionedExpirationTimer"
case storageServiceRecordIkm = "ssre2"
}
public init(hasSVRBackups: Bool) {
self.hasSVRBackups = hasSVRBackups
}
var requestParameters: [String: NSNumber] {
let jsonData = try! JSONEncoder().encode(self)
return try! JSONSerialization.jsonObject(with: jsonData) as! [String: NSNumber]
}
}
}