2015-12-07 03:31:43 +01:00
|
|
|
//
|
2019-01-04 15:19:41 +01:00
|
|
|
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
2015-12-07 03:31:43 +01:00
|
|
|
//
|
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
#import "TSAccountManager.h"
|
2018-01-12 17:15:31 +01:00
|
|
|
#import "AppContext.h"
|
2018-10-12 17:11:03 +02:00
|
|
|
#import "AppReadiness.h"
|
2017-09-18 15:40:28 +02:00
|
|
|
#import "NSNotificationCenter+OWS.h"
|
2015-12-07 03:31:43 +01:00
|
|
|
#import "NSURLSessionDataTask+StatusCode.h"
|
2016-11-03 21:10:06 +01:00
|
|
|
#import "OWSError.h"
|
2018-03-05 15:30:58 +01:00
|
|
|
#import "OWSPrimaryStorage+SessionStore.h"
|
2018-03-02 04:49:05 +01:00
|
|
|
#import "OWSRequestFactory.h"
|
2018-10-18 17:04:17 +02:00
|
|
|
#import "ProfileManagerProtocol.h"
|
2018-10-10 23:09:35 +02:00
|
|
|
#import "SSKEnvironment.h"
|
2015-12-07 03:31:43 +01:00
|
|
|
#import "TSNetworkManager.h"
|
|
|
|
#import "TSPreKeyManager.h"
|
2017-10-10 21:06:45 +02:00
|
|
|
#import "YapDatabaseConnection+OWS.h"
|
2018-06-15 18:52:45 +02:00
|
|
|
#import "YapDatabaseTransaction+OWS.h"
|
2018-10-12 17:11:03 +02:00
|
|
|
#import <PromiseKit/AnyPromise.h>
|
|
|
|
#import <Reachability/Reachability.h>
|
2018-09-21 21:41:10 +02:00
|
|
|
#import <SignalCoreKit/NSData+OWS.h>
|
2018-09-25 18:49:02 +02:00
|
|
|
#import <SignalCoreKit/Randomness.h>
|
2018-10-12 17:11:03 +02:00
|
|
|
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
2017-12-20 17:28:07 +01:00
|
|
|
#import <YapDatabase/YapDatabase.h>
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
2017-04-08 03:28:34 +02:00
|
|
|
NSString *const TSRegistrationErrorDomain = @"TSRegistrationErrorDomain";
|
|
|
|
NSString *const TSRegistrationErrorUserInfoHTTPStatus = @"TSHTTPStatus";
|
2017-12-04 18:38:44 +01:00
|
|
|
NSString *const RegistrationStateDidChangeNotification = @"RegistrationStateDidChangeNotification";
|
2017-05-10 22:00:36 +02:00
|
|
|
NSString *const kNSNotificationName_LocalNumberDidChange = @"kNSNotificationName_LocalNumberDidChange";
|
2017-04-08 03:28:34 +02:00
|
|
|
|
2017-08-02 21:37:52 +02:00
|
|
|
NSString *const TSAccountManager_RegisteredNumberKey = @"TSStorageRegisteredNumberKey";
|
2018-06-15 18:45:11 +02:00
|
|
|
NSString *const TSAccountManager_IsDeregisteredKey = @"TSAccountManager_IsDeregisteredKey";
|
2018-06-18 16:54:06 +02:00
|
|
|
NSString *const TSAccountManager_ReregisteringPhoneNumberKey = @"TSAccountManager_ReregisteringPhoneNumberKey";
|
2017-08-02 21:37:52 +02:00
|
|
|
NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegistrationId";
|
2018-11-26 17:19:11 +01:00
|
|
|
NSString *const TSAccountManager_HasPendingRestoreDecisionKey = @"TSAccountManager_HasPendingRestoreDecisionKey";
|
2017-08-02 21:37:52 +02:00
|
|
|
|
2017-10-10 21:06:45 +02:00
|
|
|
NSString *const TSAccountManager_UserAccountCollection = @"TSStorageUserAccountCollection";
|
|
|
|
NSString *const TSAccountManager_ServerAuthToken = @"TSStorageServerAuthToken";
|
|
|
|
NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignalingKey";
|
2018-10-01 22:08:11 +02:00
|
|
|
NSString *const TSAccountManager_ManualMessageFetchKey = @"TSAccountManager_ManualMessageFetchKey";
|
2018-10-12 17:11:03 +02:00
|
|
|
NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountManager_NeedsAccountAttributesUpdateKey";
|
2017-10-10 21:06:45 +02:00
|
|
|
|
2015-12-07 03:31:43 +01:00
|
|
|
@interface TSAccountManager ()
|
|
|
|
|
2018-08-15 16:38:47 +02:00
|
|
|
@property (atomic, readonly) BOOL isRegistered;
|
2018-05-30 21:41:01 +02:00
|
|
|
|
2017-08-02 21:15:31 +02:00
|
|
|
@property (nonatomic, nullable) NSString *cachedLocalNumber;
|
2017-08-02 21:37:52 +02:00
|
|
|
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-06-15 18:45:11 +02:00
|
|
|
@property (nonatomic, nullable) NSNumber *cachedIsDeregistered;
|
|
|
|
|
2018-10-12 17:11:03 +02:00
|
|
|
@property (nonatomic) Reachability *reachability;
|
|
|
|
|
2015-12-07 03:31:43 +01:00
|
|
|
@end
|
|
|
|
|
2017-04-08 03:28:34 +02:00
|
|
|
#pragma mark -
|
|
|
|
|
2015-12-07 03:31:43 +01:00
|
|
|
@implementation TSAccountManager
|
|
|
|
|
2017-08-02 21:37:52 +02:00
|
|
|
@synthesize isRegistered = _isRegistered;
|
|
|
|
|
2018-10-10 23:09:35 +02:00
|
|
|
- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
|
2016-11-03 21:10:06 +01:00
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (!self) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2018-03-05 15:30:58 +01:00
|
|
|
_dbConnection = [primaryStorage newDatabaseConnection];
|
2018-10-12 17:11:03 +02:00
|
|
|
self.reachability = [Reachability reachabilityForInternetConnection];
|
2016-11-03 21:10:06 +01:00
|
|
|
|
2017-04-01 00:45:46 +02:00
|
|
|
OWSSingletonAssert();
|
|
|
|
|
2018-01-12 17:15:31 +01:00
|
|
|
if (!CurrentAppContext().isMainApp) {
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(yapDatabaseModifiedExternally:)
|
|
|
|
name:YapDatabaseModifiedExternallyNotification
|
|
|
|
object:nil];
|
|
|
|
}
|
|
|
|
|
2018-11-02 18:51:46 +01:00
|
|
|
[AppReadiness runNowOrWhenAppDidBecomeReady:^{
|
2018-12-11 15:39:29 +01:00
|
|
|
[[self updateAccountAttributesIfNecessary] retainUntilComplete];
|
2018-10-12 17:11:03 +02:00
|
|
|
}];
|
|
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(reachabilityChanged)
|
|
|
|
name:kReachabilityChangedNotification
|
|
|
|
object:nil];
|
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2018-01-12 17:15:31 +01:00
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
}
|
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
+ (instancetype)sharedInstance
|
|
|
|
{
|
2018-10-10 23:09:35 +02:00
|
|
|
OWSAssertDebug(SSKEnvironment.shared.tsAccountManager);
|
|
|
|
|
|
|
|
return SSKEnvironment.shared.tsAccountManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Dependencies
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-10-10 23:09:35 +02:00
|
|
|
- (TSNetworkManager *)networkManager
|
|
|
|
{
|
|
|
|
OWSAssertDebug(SSKEnvironment.shared.networkManager);
|
|
|
|
|
|
|
|
return SSKEnvironment.shared.networkManager;
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2018-10-18 17:04:17 +02:00
|
|
|
- (id<ProfileManagerProtocol>)profileManager {
|
|
|
|
OWSAssertDebug(SSKEnvironment.shared.profileManager);
|
|
|
|
|
|
|
|
return SSKEnvironment.shared.profileManager;
|
|
|
|
}
|
|
|
|
|
2018-10-10 23:09:35 +02:00
|
|
|
#pragma mark -
|
|
|
|
|
2017-05-10 22:00:36 +02:00
|
|
|
- (void)setPhoneNumberAwaitingVerification:(NSString *_Nullable)phoneNumberAwaitingVerification
|
|
|
|
{
|
|
|
|
_phoneNumberAwaitingVerification = phoneNumberAwaitingVerification;
|
|
|
|
|
2017-09-18 15:40:28 +02:00
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationNameAsync:kNSNotificationName_LocalNumberDidChange
|
|
|
|
object:nil
|
|
|
|
userInfo:nil];
|
2017-05-10 22:00:36 +02:00
|
|
|
}
|
|
|
|
|
2018-11-26 17:19:11 +01:00
|
|
|
- (OWSRegistrationState)registrationState
|
|
|
|
{
|
|
|
|
if (!self.isRegistered) {
|
|
|
|
return OWSRegistrationState_Unregistered;
|
|
|
|
} else if (self.isDeregistered) {
|
|
|
|
if (self.isReregistering) {
|
|
|
|
return OWSRegistrationState_Reregistering;
|
|
|
|
} else {
|
|
|
|
return OWSRegistrationState_Deregistered;
|
|
|
|
}
|
|
|
|
} else if (self.isDeregistered) {
|
|
|
|
return OWSRegistrationState_PendingBackupRestore;
|
|
|
|
} else {
|
|
|
|
return OWSRegistrationState_Registered;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-02 21:37:52 +02:00
|
|
|
- (BOOL)isRegistered
|
|
|
|
{
|
2018-07-26 22:16:33 +02:00
|
|
|
@synchronized (self) {
|
|
|
|
if (_isRegistered) {
|
|
|
|
return YES;
|
|
|
|
} else {
|
2017-08-02 21:37:52 +02:00
|
|
|
// Cache this once it's true since it's called alot, involves a dbLookup, and once set - it doesn't change.
|
|
|
|
_isRegistered = [self storedLocalNumber] != nil;
|
|
|
|
}
|
2018-08-15 16:38:47 +02:00
|
|
|
return _isRegistered;
|
2017-08-02 21:37:52 +02:00
|
|
|
}
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2018-11-26 17:19:11 +01:00
|
|
|
- (BOOL)isRegisteredAndReady
|
|
|
|
{
|
|
|
|
return self.registrationState == OWSRegistrationState_Registered;
|
|
|
|
}
|
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
- (void)didRegister
|
|
|
|
{
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogInfo(@"didRegister");
|
2016-11-03 21:10:06 +01:00
|
|
|
NSString *phoneNumber = self.phoneNumberAwaitingVerification;
|
2015-12-07 03:31:43 +01:00
|
|
|
|
|
|
|
if (!phoneNumber) {
|
2018-10-30 16:41:43 +01:00
|
|
|
OWSFail(@"phoneNumber was unexpectedly nil");
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2017-08-02 21:37:52 +02:00
|
|
|
[self storeLocalNumber:phoneNumber];
|
2017-04-08 03:28:34 +02:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
// Warm these cached values.
|
|
|
|
[self isRegistered];
|
|
|
|
[self localNumber];
|
2018-06-15 18:45:11 +02:00
|
|
|
[self isDeregistered];
|
2018-11-26 17:19:11 +01:00
|
|
|
|
|
|
|
[self postRegistrationStateDidChangeNotification];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
+ (nullable NSString *)localNumber
|
|
|
|
{
|
2017-08-02 21:15:31 +02:00
|
|
|
return [[self sharedInstance] localNumber];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (nullable NSString *)localNumber
|
|
|
|
{
|
|
|
|
NSString *awaitingVerif = self.phoneNumberAwaitingVerification;
|
2015-12-07 03:31:43 +01:00
|
|
|
if (awaitingVerif) {
|
|
|
|
return awaitingVerif;
|
|
|
|
}
|
|
|
|
|
2017-08-02 21:15:31 +02:00
|
|
|
// Cache this since we access this a lot, and once set it will not change.
|
|
|
|
@synchronized(self)
|
|
|
|
{
|
|
|
|
if (self.cachedLocalNumber == nil) {
|
2017-08-02 21:37:52 +02:00
|
|
|
self.cachedLocalNumber = self.storedLocalNumber;
|
2017-08-02 21:15:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return self.cachedLocalNumber;
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2017-08-02 21:37:52 +02:00
|
|
|
- (nullable NSString *)storedLocalNumber
|
|
|
|
{
|
|
|
|
@synchronized (self) {
|
|
|
|
return [self.dbConnection stringForKey:TSAccountManager_RegisteredNumberKey
|
2017-10-10 21:06:45 +02:00
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
2017-08-02 21:37:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-04 15:19:41 +01:00
|
|
|
- (nullable NSString *)storedOrCachedLocalNumber:(YapDatabaseReadTransaction *)transaction
|
2018-12-21 19:29:22 +01:00
|
|
|
{
|
2019-01-04 15:19:41 +01:00
|
|
|
@synchronized(self) {
|
|
|
|
if (self.cachedLocalNumber) {
|
|
|
|
return self.cachedLocalNumber;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-21 19:29:22 +01:00
|
|
|
return [transaction stringForKey:TSAccountManager_RegisteredNumberKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
}
|
|
|
|
|
2017-08-02 21:37:52 +02:00
|
|
|
- (void)storeLocalNumber:(NSString *)localNumber
|
|
|
|
{
|
|
|
|
@synchronized (self) {
|
|
|
|
[self.dbConnection setObject:localNumber
|
|
|
|
forKey:TSAccountManager_RegisteredNumberKey
|
2017-10-10 21:06:45 +02:00
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
2018-06-18 16:54:06 +02:00
|
|
|
|
|
|
|
[self.dbConnection removeObjectForKey:TSAccountManager_ReregisteringPhoneNumberKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
|
|
|
|
self.phoneNumberAwaitingVerification = nil;
|
2018-06-18 17:10:09 +02:00
|
|
|
|
|
|
|
self.cachedLocalNumber = localNumber;
|
2017-08-02 21:37:52 +02:00
|
|
|
}
|
|
|
|
}
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-01-23 19:58:45 +01:00
|
|
|
+ (uint32_t)getOrGenerateRegistrationId:(YapDatabaseReadWriteTransaction *)transaction
|
|
|
|
{
|
|
|
|
return [[self sharedInstance] getOrGenerateRegistrationId:transaction];
|
|
|
|
}
|
|
|
|
|
2017-08-02 21:37:52 +02:00
|
|
|
- (uint32_t)getOrGenerateRegistrationId
|
2018-01-23 19:58:45 +01:00
|
|
|
{
|
2018-01-30 21:05:04 +01:00
|
|
|
__block uint32_t result;
|
2018-01-23 19:58:45 +01:00
|
|
|
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
2018-01-30 21:05:04 +01:00
|
|
|
result = [self getOrGenerateRegistrationId:transaction];
|
2018-01-23 19:58:45 +01:00
|
|
|
}];
|
2018-01-30 21:05:04 +01:00
|
|
|
return result;
|
2018-01-23 19:58:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (uint32_t)getOrGenerateRegistrationId:(YapDatabaseReadWriteTransaction *)transaction
|
2017-08-02 21:37:52 +02:00
|
|
|
{
|
2019-04-12 22:51:14 +02:00
|
|
|
// Unlike other methods in this class, there's no need for a `@synchronized` block
|
|
|
|
// here, since we're already in a write transaction, and all writes occur on a serial queue.
|
|
|
|
//
|
|
|
|
// Since other code in this class which uses @synchronized(self) also needs to open write
|
|
|
|
// transaction, using @synchronized(self) here, inside of a WriteTransaction risks deadlock.
|
|
|
|
uint32_t registrationID = [[transaction objectForKey:TSAccountManager_LocalRegistrationIdKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection] unsignedIntValue];
|
|
|
|
|
|
|
|
if (registrationID == 0) {
|
|
|
|
registrationID = (uint32_t)arc4random_uniform(16380) + 1;
|
|
|
|
OWSLogWarn(@"Generated a new registrationID: %u", registrationID);
|
|
|
|
|
|
|
|
[transaction setObject:[NSNumber numberWithUnsignedInteger:registrationID]
|
|
|
|
forKey:TSAccountManager_LocalRegistrationIdKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
2019-04-12 22:51:14 +02:00
|
|
|
return registrationID;
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
- (void)registerForPushNotificationsWithPushToken:(NSString *)pushToken
|
|
|
|
voipToken:(NSString *)voipToken
|
2017-11-08 20:04:51 +01:00
|
|
|
success:(void (^)(void))successHandler
|
2016-11-03 21:10:06 +01:00
|
|
|
failure:(void (^)(NSError *))failureHandler
|
2017-05-17 20:26:51 +02:00
|
|
|
{
|
|
|
|
[self registerForPushNotificationsWithPushToken:pushToken
|
|
|
|
voipToken:voipToken
|
|
|
|
success:successHandler
|
|
|
|
failure:failureHandler
|
|
|
|
remainingRetries:3];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)registerForPushNotificationsWithPushToken:(NSString *)pushToken
|
|
|
|
voipToken:(NSString *)voipToken
|
2017-11-08 20:04:51 +01:00
|
|
|
success:(void (^)(void))successHandler
|
2017-05-17 20:26:51 +02:00
|
|
|
failure:(void (^)(NSError *))failureHandler
|
|
|
|
remainingRetries:(int)remainingRetries
|
2016-11-03 21:10:06 +01:00
|
|
|
{
|
2020-04-15 05:40:19 +02:00
|
|
|
BOOL isUsingFullAPNs = [NSUserDefaults.standardUserDefaults boolForKey:@"isUsingFullAPNs"];
|
2020-04-16 05:58:43 +02:00
|
|
|
AnyPromise *promise = isUsingFullAPNs ? [LKPushNotificationManager registerWithToken:pushToken hexEncodedPublicKey:self.localNumber]
|
|
|
|
: [LKPushNotificationManager registerWithToken:pushToken];
|
|
|
|
promise
|
|
|
|
.then(^() {
|
|
|
|
successHandler();
|
|
|
|
})
|
|
|
|
.catch(^(NSError *error) {
|
|
|
|
if (remainingRetries > 0) {
|
|
|
|
[self registerForPushNotificationsWithPushToken:pushToken voipToken:voipToken success:successHandler failure:failureHandler
|
|
|
|
remainingRetries:remainingRetries - 1];
|
|
|
|
} else {
|
|
|
|
if (!IsNSErrorNetworkFailure(error)) {
|
|
|
|
OWSProdError([OWSAnalyticsEvents accountsErrorRegisterPushTokensFailed]);
|
2017-05-17 20:26:51 +02:00
|
|
|
}
|
2020-04-16 05:58:43 +02:00
|
|
|
failureHandler(error);
|
|
|
|
}
|
|
|
|
});
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2018-11-26 16:24:36 +01:00
|
|
|
- (void)registerWithPhoneNumber:(NSString *)phoneNumber
|
2019-02-14 18:41:48 +01:00
|
|
|
captchaToken:(nullable NSString *)captchaToken
|
2017-11-08 20:04:51 +01:00
|
|
|
success:(void (^)(void))successBlock
|
2016-11-03 21:10:06 +01:00
|
|
|
failure:(void (^)(NSError *error))failureBlock
|
2015-12-07 03:31:43 +01:00
|
|
|
smsVerification:(BOOL)isSMS
|
|
|
|
|
|
|
|
{
|
|
|
|
if ([self isRegistered]) {
|
|
|
|
failureBlock([NSError errorWithDomain:@"tsaccountmanager.verify" code:4000 userInfo:nil]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-03 22:32:53 +01:00
|
|
|
// The country code of TSAccountManager.phoneNumberAwaitingVerification is used to
|
|
|
|
// determine whether or not to use domain fronting, so it needs to be set _before_
|
|
|
|
// we make our verification code request.
|
2018-11-26 16:24:36 +01:00
|
|
|
self.phoneNumberAwaitingVerification = phoneNumber;
|
2017-07-24 17:06:19 +02:00
|
|
|
|
2018-03-02 04:49:05 +01:00
|
|
|
TSRequest *request =
|
|
|
|
[OWSRequestFactory requestVerificationCodeRequestWithPhoneNumber:phoneNumber
|
2019-02-14 18:41:48 +01:00
|
|
|
captchaToken:captchaToken
|
2018-03-02 04:49:05 +01:00
|
|
|
transport:(isSMS ? TSVerificationTransportSMS
|
|
|
|
: TSVerificationTransportVoice)];
|
|
|
|
[[TSNetworkManager sharedManager] makeRequest:request
|
2015-12-07 03:31:43 +01:00
|
|
|
success:^(NSURLSessionDataTask *task, id responseObject) {
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogInfo(@"Successfully requested verification code request for number: %@ method:%@",
|
2016-11-03 21:10:06 +01:00
|
|
|
phoneNumber,
|
|
|
|
isSMS ? @"SMS" : @"Voice");
|
|
|
|
successBlock();
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
2017-07-24 17:06:19 +02:00
|
|
|
if (!IsNSErrorNetworkFailure(error)) {
|
2017-07-27 18:29:05 +02:00
|
|
|
OWSProdError([OWSAnalyticsEvents accountsErrorVerificationCodeRequestFailed]);
|
2017-07-24 17:06:19 +02:00
|
|
|
}
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogError(@"Failed to request verification code request with error:%@", error);
|
2016-11-03 21:10:06 +01:00
|
|
|
failureBlock(error);
|
2015-12-07 03:31:43 +01:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2019-02-14 18:41:48 +01:00
|
|
|
- (void)rerequestSMSWithCaptchaToken:(nullable NSString *)captchaToken
|
|
|
|
success:(void (^)(void))successBlock
|
|
|
|
failure:(void (^)(NSError *error))failureBlock
|
2016-11-03 21:10:06 +01:00
|
|
|
{
|
2019-02-14 18:41:48 +01:00
|
|
|
// TODO: Can we remove phoneNumberAwaitingVerification?
|
2018-11-26 16:24:36 +01:00
|
|
|
NSString *number = self.phoneNumberAwaitingVerification;
|
2018-09-06 19:01:24 +02:00
|
|
|
OWSAssertDebug(number);
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2019-02-14 18:41:48 +01:00
|
|
|
[self registerWithPhoneNumber:number
|
|
|
|
captchaToken:captchaToken
|
|
|
|
success:successBlock
|
|
|
|
failure:failureBlock
|
|
|
|
smsVerification:YES];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 18:41:48 +01:00
|
|
|
- (void)rerequestVoiceWithCaptchaToken:(nullable NSString *)captchaToken
|
|
|
|
success:(void (^)(void))successBlock
|
|
|
|
failure:(void (^)(NSError *error))failureBlock
|
2016-11-03 21:10:06 +01:00
|
|
|
{
|
2018-11-26 16:24:36 +01:00
|
|
|
NSString *number = self.phoneNumberAwaitingVerification;
|
2018-09-06 19:01:24 +02:00
|
|
|
OWSAssertDebug(number);
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2019-02-14 18:41:48 +01:00
|
|
|
[self registerWithPhoneNumber:number
|
|
|
|
captchaToken:captchaToken
|
|
|
|
success:successBlock
|
|
|
|
failure:failureBlock
|
|
|
|
smsVerification:NO];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
- (void)verifyAccountWithCode:(NSString *)verificationCode
|
2018-03-01 20:42:54 +01:00
|
|
|
pin:(nullable NSString *)pin
|
2017-11-08 20:04:51 +01:00
|
|
|
success:(void (^)(void))successBlock
|
2016-11-03 21:10:06 +01:00
|
|
|
failure:(void (^)(NSError *error))failureBlock
|
|
|
|
{
|
|
|
|
NSString *authToken = [[self class] generateNewAccountAuthenticationToken];
|
|
|
|
NSString *phoneNumber = self.phoneNumberAwaitingVerification;
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-09-06 19:01:24 +02:00
|
|
|
OWSAssertDebug(authToken);
|
|
|
|
OWSAssertDebug(phoneNumber);
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-10-01 22:08:11 +02:00
|
|
|
TSRequest *request = [OWSRequestFactory verifyCodeRequestWithVerificationCode:verificationCode
|
|
|
|
forNumber:phoneNumber
|
|
|
|
pin:pin
|
|
|
|
authKey:authToken];
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
[self.networkManager makeRequest:request
|
2015-12-07 03:31:43 +01:00
|
|
|
success:^(NSURLSessionDataTask *task, id responseObject) {
|
2016-11-03 21:10:06 +01:00
|
|
|
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
|
|
|
|
long statuscode = response.statusCode;
|
|
|
|
|
|
|
|
switch (statuscode) {
|
|
|
|
case 200:
|
|
|
|
case 204: {
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogInfo(@"Verification code accepted.");
|
2019-01-08 21:10:32 +01:00
|
|
|
|
|
|
|
[self storeServerAuthToken:authToken];
|
|
|
|
|
|
|
|
[[[SignalServiceRestClient new] updateAccountAttributesObjC]
|
|
|
|
.thenInBackground(^{
|
|
|
|
return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
|
|
|
|
[TSPreKeyManager
|
|
|
|
createPreKeysWithSuccess:^{
|
|
|
|
resolve(@(1));
|
|
|
|
}
|
|
|
|
failure:^(NSError *error) {
|
|
|
|
resolve(error);
|
|
|
|
}];
|
|
|
|
}];
|
|
|
|
})
|
|
|
|
.then(^{
|
|
|
|
[self.profileManager fetchLocalUsersProfile];
|
|
|
|
})
|
|
|
|
.then(^{
|
|
|
|
successBlock();
|
|
|
|
})
|
|
|
|
.catchInBackground(^(NSError *error) {
|
|
|
|
OWSLogError(@"Error: %@", error);
|
|
|
|
failureBlock(error);
|
|
|
|
}) retainUntilComplete];
|
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogError(@"Unexpected status while verifying code: %ld", statuscode);
|
2016-11-03 21:10:06 +01:00
|
|
|
NSError *error = OWSErrorMakeUnableToProcessServerResponseError();
|
2015-12-07 03:31:43 +01:00
|
|
|
failureBlock(error);
|
2016-11-03 21:10:06 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
2017-07-24 17:06:19 +02:00
|
|
|
if (!IsNSErrorNetworkFailure(error)) {
|
2017-07-27 18:29:05 +02:00
|
|
|
OWSProdError([OWSAnalyticsEvents accountsErrorVerifyAccountRequestFailed]);
|
2017-07-24 17:06:19 +02:00
|
|
|
}
|
2018-10-12 01:06:12 +02:00
|
|
|
OWSAssertDebug([error.domain isEqualToString:TSNetworkManagerErrorDomain]);
|
2018-03-05 17:05:21 +01:00
|
|
|
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogWarn(@"Error verifying code: %@", error.debugDescription);
|
2018-03-05 17:05:21 +01:00
|
|
|
|
2016-11-03 21:10:06 +01:00
|
|
|
switch (error.code) {
|
|
|
|
case 403: {
|
|
|
|
NSError *userError = OWSErrorWithCodeDescription(OWSErrorCodeUserError,
|
|
|
|
NSLocalizedString(@"REGISTRATION_VERIFICATION_FAILED_WRONG_CODE_DESCRIPTION",
|
2018-03-05 17:08:42 +01:00
|
|
|
"Error message indicating that registration failed due to a missing or incorrect "
|
2018-03-05 17:05:21 +01:00
|
|
|
"verification code."));
|
|
|
|
failureBlock(userError);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 413: {
|
|
|
|
// In the case of the "rate limiting" error, we want to show the
|
|
|
|
// "recovery suggestion", not the error's "description."
|
|
|
|
NSError *userError
|
|
|
|
= OWSErrorWithCodeDescription(OWSErrorCodeUserError, error.localizedRecoverySuggestion);
|
2016-11-03 21:10:06 +01:00
|
|
|
failureBlock(userError);
|
|
|
|
break;
|
|
|
|
}
|
2018-03-01 20:42:54 +01:00
|
|
|
case 423: {
|
2018-03-05 17:27:56 +01:00
|
|
|
NSString *localizedMessage = NSLocalizedString(@"REGISTRATION_VERIFICATION_FAILED_WRONG_PIN",
|
|
|
|
"Error message indicating that registration failed due to a missing or incorrect 2FA PIN.");
|
2018-08-27 18:55:37 +02:00
|
|
|
OWSLogError(@"2FA PIN required: %ld", (long)error.code);
|
2018-03-05 17:27:56 +01:00
|
|
|
NSError *error
|
|
|
|
= OWSErrorWithCodeDescription(OWSErrorCodeRegistrationMissing2FAPIN, localizedMessage);
|
2018-03-01 20:42:54 +01:00
|
|
|
failureBlock(error);
|
|
|
|
break;
|
|
|
|
}
|
2016-11-03 21:10:06 +01:00
|
|
|
default: {
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogError(@"verifying code failed with unknown error: %@", error);
|
2016-11-03 21:10:06 +01:00
|
|
|
failureBlock(error);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-12-07 03:31:43 +01:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark Server keying material
|
|
|
|
|
|
|
|
+ (NSString *)generateNewAccountAuthenticationToken {
|
2018-07-27 20:40:58 +02:00
|
|
|
NSData *authToken = [Randomness generateRandomBytes:16];
|
2015-12-07 03:31:43 +01:00
|
|
|
NSString *authTokenPrint = [[NSData dataWithData:authToken] hexadecimalString];
|
|
|
|
return authTokenPrint;
|
|
|
|
}
|
|
|
|
|
2017-10-10 21:06:45 +02:00
|
|
|
+ (nullable NSString *)signalingKey
|
|
|
|
{
|
|
|
|
return [[self sharedInstance] signalingKey];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (nullable NSString *)signalingKey
|
|
|
|
{
|
|
|
|
return [self.dbConnection stringForKey:TSAccountManager_ServerSignalingKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (nullable NSString *)serverAuthToken
|
|
|
|
{
|
|
|
|
return [[self sharedInstance] serverAuthToken];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (nullable NSString *)serverAuthToken
|
|
|
|
{
|
|
|
|
return [self.dbConnection stringForKey:TSAccountManager_ServerAuthToken
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
}
|
|
|
|
|
2018-12-20 15:19:16 +01:00
|
|
|
- (void)storeServerAuthToken:(NSString *)authToken
|
2017-10-10 21:06:45 +02:00
|
|
|
{
|
|
|
|
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[transaction setObject:authToken
|
|
|
|
forKey:TSAccountManager_ServerAuthToken
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2017-11-08 20:04:51 +01:00
|
|
|
+ (void)unregisterTextSecureWithSuccess:(void (^)(void))success failure:(void (^)(NSError *error))failureBlock
|
2016-11-03 21:10:06 +01:00
|
|
|
{
|
2018-03-02 04:49:05 +01:00
|
|
|
TSRequest *request = [OWSRequestFactory unregisterAccountRequest];
|
|
|
|
[[TSNetworkManager sharedManager] makeRequest:request
|
2015-12-07 03:31:43 +01:00
|
|
|
success:^(NSURLSessionDataTask *task, id responseObject) {
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogInfo(@"Successfully unregistered");
|
2016-11-03 21:10:06 +01:00
|
|
|
success();
|
2017-04-08 03:28:34 +02:00
|
|
|
|
2017-07-31 22:45:06 +02:00
|
|
|
// This is called from `[AppSettingsViewController proceedToUnregistration]` whose
|
2017-04-11 23:38:06 +02:00
|
|
|
// success handler calls `[Environment resetAppData]`.
|
|
|
|
// This method, after calling that success handler, fires
|
2017-12-04 18:38:44 +01:00
|
|
|
// `RegistrationStateDidChangeNotification` which is only safe to fire after
|
2017-04-11 23:38:06 +02:00
|
|
|
// the data store is reset.
|
|
|
|
|
2018-11-26 17:19:11 +01:00
|
|
|
[self.sharedInstance postRegistrationStateDidChangeNotification];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
2017-07-24 17:06:19 +02:00
|
|
|
if (!IsNSErrorNetworkFailure(error)) {
|
2017-07-27 18:29:05 +02:00
|
|
|
OWSProdError([OWSAnalyticsEvents accountsErrorUnregisterAccountRequestFailed]);
|
2017-07-24 17:06:19 +02:00
|
|
|
}
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogError(@"Failed to unregister with error: %@", error);
|
2016-11-03 21:10:06 +01:00
|
|
|
failureBlock(error);
|
2015-12-07 03:31:43 +01:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2018-01-12 17:15:31 +01:00
|
|
|
- (void)yapDatabaseModifiedExternally:(NSNotification *)notification
|
|
|
|
{
|
|
|
|
OWSAssertIsOnMainThread();
|
|
|
|
|
2018-08-27 18:09:39 +02:00
|
|
|
OWSLogVerbose(@"");
|
2018-01-12 17:15:31 +01:00
|
|
|
|
|
|
|
// Any database write by the main app might reflect a deregistration,
|
|
|
|
// so clear the cached "is registered" state. This will significantly
|
|
|
|
// erode the value of this cache in the SAE.
|
|
|
|
@synchronized(self)
|
|
|
|
{
|
|
|
|
_isRegistered = NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-18 16:54:06 +02:00
|
|
|
#pragma mark - De-Registration
|
2018-06-15 18:45:11 +02:00
|
|
|
|
|
|
|
- (BOOL)isDeregistered
|
|
|
|
{
|
|
|
|
// Cache this since we access this a lot, and once set it will not change.
|
|
|
|
@synchronized(self) {
|
|
|
|
if (self.cachedIsDeregistered == nil) {
|
|
|
|
self.cachedIsDeregistered = @([self.dbConnection boolForKey:TSAccountManager_IsDeregisteredKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection
|
|
|
|
defaultValue:NO]);
|
|
|
|
}
|
|
|
|
|
2018-09-06 19:01:24 +02:00
|
|
|
OWSAssertDebug(self.cachedIsDeregistered);
|
2018-06-15 18:52:45 +02:00
|
|
|
return self.cachedIsDeregistered.boolValue;
|
|
|
|
}
|
2018-06-15 18:45:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setIsDeregistered:(BOOL)isDeregistered
|
|
|
|
{
|
|
|
|
@synchronized(self) {
|
2018-06-15 18:52:45 +02:00
|
|
|
if (self.cachedIsDeregistered && self.cachedIsDeregistered.boolValue == isDeregistered) {
|
|
|
|
return;
|
|
|
|
}
|
2018-06-15 18:45:11 +02:00
|
|
|
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSLogWarn(@"isDeregistered: %d", isDeregistered);
|
2018-06-15 18:45:11 +02:00
|
|
|
|
2018-06-15 18:52:45 +02:00
|
|
|
self.cachedIsDeregistered = @(isDeregistered);
|
2018-06-15 18:45:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
2018-06-15 18:52:45 +02:00
|
|
|
[transaction setObject:@(isDeregistered)
|
|
|
|
forKey:TSAccountManager_IsDeregisteredKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
2018-06-15 18:45:11 +02:00
|
|
|
}];
|
|
|
|
|
2018-11-26 17:19:11 +01:00
|
|
|
[self postRegistrationStateDidChangeNotification];
|
2018-06-15 18:45:11 +02:00
|
|
|
}
|
|
|
|
|
2018-06-18 16:54:06 +02:00
|
|
|
#pragma mark - Re-registration
|
|
|
|
|
|
|
|
- (BOOL)resetForReregistration
|
|
|
|
{
|
|
|
|
@synchronized(self) {
|
|
|
|
NSString *_Nullable localNumber = self.localNumber;
|
|
|
|
if (!localNumber) {
|
2018-08-27 18:51:32 +02:00
|
|
|
OWSFailDebug(@"can't re-register without valid local number.");
|
2018-06-18 16:54:06 +02:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
_isRegistered = NO;
|
|
|
|
_cachedLocalNumber = nil;
|
|
|
|
_phoneNumberAwaitingVerification = nil;
|
|
|
|
_cachedIsDeregistered = nil;
|
|
|
|
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[transaction removeAllObjectsInCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
|
|
|
|
[[OWSPrimaryStorage sharedManager] resetSessionStore:transaction];
|
|
|
|
|
|
|
|
[transaction setObject:localNumber
|
|
|
|
forKey:TSAccountManager_ReregisteringPhoneNumberKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
}];
|
2018-11-26 17:19:11 +01:00
|
|
|
|
|
|
|
[self postRegistrationStateDidChangeNotification];
|
|
|
|
|
2018-06-18 16:54:06 +02:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-13 22:18:00 +01:00
|
|
|
- (nullable NSString *)reregisterationPhoneNumber
|
2018-06-18 16:54:06 +02:00
|
|
|
{
|
2018-09-06 19:01:24 +02:00
|
|
|
OWSAssertDebug([self isReregistering]);
|
2018-06-18 16:54:06 +02:00
|
|
|
|
|
|
|
NSString *_Nullable result = [self.dbConnection stringForKey:TSAccountManager_ReregisteringPhoneNumberKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
2018-09-06 19:01:24 +02:00
|
|
|
OWSAssertDebug(result);
|
2018-06-18 16:54:06 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)isReregistering
|
|
|
|
{
|
|
|
|
return nil !=
|
|
|
|
[self.dbConnection stringForKey:TSAccountManager_ReregisteringPhoneNumberKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
}
|
|
|
|
|
2018-11-26 17:19:11 +01:00
|
|
|
- (BOOL)hasPendingBackupRestoreDecision
|
|
|
|
{
|
|
|
|
return [self.dbConnection boolForKey:TSAccountManager_HasPendingRestoreDecisionKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection
|
|
|
|
defaultValue:NO];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setHasPendingBackupRestoreDecision:(BOOL)value
|
|
|
|
{
|
|
|
|
OWSLogInfo(@"%d", value);
|
|
|
|
|
|
|
|
[self.dbConnection setBool:value
|
|
|
|
forKey:TSAccountManager_HasPendingRestoreDecisionKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
|
|
|
|
[self postRegistrationStateDidChangeNotification];
|
|
|
|
}
|
|
|
|
|
2018-10-01 22:08:11 +02:00
|
|
|
- (BOOL)isManualMessageFetchEnabled
|
|
|
|
{
|
|
|
|
return [self.dbConnection boolForKey:TSAccountManager_ManualMessageFetchKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection
|
|
|
|
defaultValue:NO];
|
|
|
|
}
|
|
|
|
|
2018-10-12 17:11:03 +02:00
|
|
|
- (AnyPromise *)setIsManualMessageFetchEnabled:(BOOL)value {
|
2018-10-01 22:08:11 +02:00
|
|
|
[self.dbConnection setBool:value
|
|
|
|
forKey:TSAccountManager_ManualMessageFetchKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
2018-10-12 17:11:03 +02:00
|
|
|
|
|
|
|
// Try to update the account attributes to reflect this change.
|
|
|
|
return [self updateAccountAttributes];
|
2018-10-01 22:08:11 +02:00
|
|
|
}
|
|
|
|
|
2018-10-10 23:09:35 +02:00
|
|
|
- (void)registerForTestsWithLocalNumber:(NSString *)localNumber
|
|
|
|
{
|
|
|
|
OWSAssertDebug(localNumber.length > 0);
|
|
|
|
|
|
|
|
[self storeLocalNumber:localNumber];
|
|
|
|
}
|
|
|
|
|
2018-10-12 17:11:03 +02:00
|
|
|
#pragma mark - Account Attributes
|
|
|
|
|
|
|
|
- (AnyPromise *)updateAccountAttributes {
|
2018-10-12 23:38:13 +02:00
|
|
|
// Enqueue a "account attribute update", recording the "request time".
|
2018-10-12 17:11:03 +02:00
|
|
|
[self.dbConnection setObject:[NSDate new]
|
|
|
|
forKey:TSAccountManager_NeedsAccountAttributesUpdateKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
|
|
|
|
return [self updateAccountAttributesIfNecessary];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (AnyPromise *)updateAccountAttributesIfNecessary {
|
2018-11-19 19:10:59 +01:00
|
|
|
if (!self.isRegistered) {
|
|
|
|
return [AnyPromise promiseWithValue:@(1)];
|
|
|
|
}
|
|
|
|
|
2019-08-30 04:12:32 +02:00
|
|
|
return [AnyPromise promiseWithValue:@(1)];
|
|
|
|
|
2018-10-12 17:11:03 +02:00
|
|
|
NSDate *_Nullable updateRequestDate =
|
|
|
|
[self.dbConnection objectForKey:TSAccountManager_NeedsAccountAttributesUpdateKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
if (!updateRequestDate) {
|
|
|
|
return [AnyPromise promiseWithValue:@(1)];
|
|
|
|
}
|
2018-11-21 20:54:32 +01:00
|
|
|
AnyPromise *promise = [self performUpdateAccountAttributes];
|
2018-10-12 17:11:03 +02:00
|
|
|
promise = promise.then(^(id value) {
|
|
|
|
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
2018-10-12 23:38:13 +02:00
|
|
|
// Clear the update request unless a new update has been requested
|
|
|
|
// while this update was in flight.
|
2018-10-12 17:11:03 +02:00
|
|
|
NSDate *_Nullable latestUpdateRequestDate =
|
|
|
|
[transaction objectForKey:TSAccountManager_NeedsAccountAttributesUpdateKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
if (latestUpdateRequestDate && [latestUpdateRequestDate isEqual:updateRequestDate]) {
|
|
|
|
[transaction removeObjectForKey:TSAccountManager_NeedsAccountAttributesUpdateKey
|
|
|
|
inCollection:TSAccountManager_UserAccountCollection];
|
|
|
|
}
|
|
|
|
}];
|
2018-11-21 20:54:32 +01:00
|
|
|
});
|
|
|
|
return promise;
|
|
|
|
}
|
2018-10-18 17:04:17 +02:00
|
|
|
|
2018-11-21 20:54:32 +01:00
|
|
|
- (AnyPromise *)performUpdateAccountAttributes
|
|
|
|
{
|
|
|
|
AnyPromise *promise = [[SignalServiceRestClient new] updateAccountAttributesObjC];
|
|
|
|
promise = promise.then(^(id value) {
|
2018-10-18 17:04:17 +02:00
|
|
|
// Fetch the local profile, as we may have changed its
|
|
|
|
// account attributes. Specifically, we need to determine
|
|
|
|
// if all devices for our account now support UD for sync
|
|
|
|
// messages.
|
|
|
|
[self.profileManager fetchLocalUsersProfile];
|
2018-10-12 17:11:03 +02:00
|
|
|
});
|
|
|
|
[promise retainUntilComplete];
|
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)reachabilityChanged {
|
|
|
|
OWSAssertIsOnMainThread();
|
|
|
|
|
2018-11-02 18:51:46 +01:00
|
|
|
[AppReadiness runNowOrWhenAppDidBecomeReady:^{
|
2018-12-11 15:39:29 +01:00
|
|
|
[[self updateAccountAttributesIfNecessary] retainUntilComplete];
|
2018-10-12 17:11:03 +02:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2018-11-26 17:19:11 +01:00
|
|
|
#pragma mark - Notifications
|
|
|
|
|
|
|
|
- (void)postRegistrationStateDidChangeNotification
|
|
|
|
{
|
|
|
|
OWSAssertIsOnMainThread();
|
|
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationNameAsync:RegistrationStateDidChangeNotification
|
|
|
|
object:nil
|
|
|
|
userInfo:nil];
|
|
|
|
}
|
|
|
|
|
2015-12-07 03:31:43 +01:00
|
|
|
@end
|
2016-11-03 21:10:06 +01:00
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_END
|