151 lines
6 KiB
Swift
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]
|
|
}
|
|
}
|
|
}
|