Fix register w/o background fetch & stale push tokens

* Separate account registration from push token registration
* Provide better errors when validation fails (e.g. numbers don't match, numbers blank)
* More logging during registration
* Call success after setting phone number to avoid any future race condition

  This isn't currently causing problems, but it's unexpected that we'd
  mutate the state *after* calling a callback which might inuitively rely
  on that state.

* Don't throw exception off thread when device keys 404's
* Better async startup handling
  - move processing off main thread
  - reduce code duplication
  - don't wrap it in a transaction in the future case where we want to
    further access the DB

// FREEBIE
pull/1/head
Michael Kirk 9 years ago committed by GitHub
parent 03f05f217c
commit 47cad611e5

@ -35,7 +35,7 @@ PODS:
- ProtocolBuffers (1.9.10)
- Reachability (3.2)
- SAMKeychain (1.5.0)
- SignalServiceKit (0.3.0):
- SignalServiceKit (0.4.0):
- '25519'
- AFNetworking
- AxolotlKit
@ -130,7 +130,7 @@ SPEC CHECKSUMS:
ProtocolBuffers: d088180c10072b3d24a9939a6314b7b9bcc2340b
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
SAMKeychain: 1fc9ae02f576365395758b12888c84704eebc423
SignalServiceKit: 8b115cfd63f9b814fa03fe61fd5d38ef9a548460
SignalServiceKit: 5c3877241082a778c8c130e1fed17d0904085205
SocketRocket: 3f77ec2104cc113add553f817ad90a77114f5d43
SQLCipher: 4c768761421736a247ed6cf412d9045615d53dff
TwistedOakCollapsingFutures: f359b90f203e9ab13dfb92c9ff41842a7fe1cd0c

@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = "SignalServiceKit"
s.version = "0.3.0"
s.version = "0.4.0"
s.summary = "An Objective-C library for communicating with the Signal messaging service."
s.description = <<-DESC

@ -9,30 +9,36 @@
#import <Foundation/Foundation.h>
#import "TSConstants.h"
NS_ASSUME_NONNULL_BEGIN
static NSString *const TSRegistrationErrorDomain = @"TSRegistrationErrorDomain";
static NSString *const TSRegistrationErrorUserInfoHTTPStatus = @"TSHTTPStatus";
typedef void (^failedBlock)(NSError *error);
@class TSNetworkManager;
@class TSStorageManager;
@interface TSAccountManager : NSObject
- (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager
storageManager:(TSStorageManager *)storageManager;
+ (instancetype)sharedInstance;
/**
* Returns if a user is registered or not
*
* @return registered or not
*/
+ (BOOL)isRegistered;
+ (void)runIfRegistered:(void (^)())block;
- (void)ifRegistered:(BOOL)isRegistered runAsync:(void (^)())block;
/**
* Returns registered number
*
* @return E164 formatted phone number
*/
+ (NSString *)localNumber;
+ (void)didRegister;
+ (nullable NSString *)localNumber;
/**
* The registration ID is unique to an installation of TextSecure, it allows to know if the app was reinstalled
@ -45,19 +51,17 @@ typedef void (^failedBlock)(NSError *error);
#pragma mark - Register with phone number
+ (void)registerWithPhoneNumber:(NSString *)phoneNumber
success:(successCompletionBlock)successBlock
failure:(failedBlock)failureBlock
success:(void (^)())successBlock
failure:(void (^)(NSError *error))failureBlock
smsVerification:(BOOL)isSMS;
+ (void)rerequestSMSWithSuccess:(successCompletionBlock)successBlock failure:(failedBlock)failureBlock;
+ (void)rerequestSMSWithSuccess:(void (^)())successBlock failure:(void (^)(NSError *error))failureBlock;
+ (void)rerequestVoiceWithSuccess:(successCompletionBlock)successBlock failure:(failedBlock)failureBlock;
+ (void)rerequestVoiceWithSuccess:(void (^)())successBlock failure:(void (^)(NSError *error))failureBlock;
+ (void)verifyAccountWithCode:(NSString *)verificationCode
pushToken:(NSString *)pushToken
voipToken:(NSString *)voipToken
success:(successCompletionBlock)successBlock
failure:(failedBlock)failureBlock;
- (void)verifyAccountWithCode:(NSString *)verificationCode
success:(void (^)())successBlock
failure:(void (^)(NSError *error))failureBlock;
#if TARGET_OS_IPHONE
@ -66,16 +70,19 @@ typedef void (^failedBlock)(NSError *error);
*
* @param pushToken Apple's Push Token
*/
- (void)registerForPushNotificationsWithPushToken:(NSString *)pushToken
voipToken:(NSString *)voipToken
success:(void (^)())successHandler
failure:(void (^)(NSError *error))failureHandler
NS_SWIFT_NAME(registerForPushNotifications(pushToken:voipToken:success:failure:));
+ (void)registerForPushNotifications:(NSString *)pushToken
voipToken:(NSString *)voipToken
success:(successCompletionBlock)success
failure:(failedBlock)failureBlock;
+ (void)obtainRPRegistrationToken:(void (^)(NSString *rpRegistrationToken))success failure:(failedBlock)failureBlock;
- (void)obtainRPRegistrationTokenWithSuccess:(void (^)(NSString *rpRegistrationToken))success
failure:(void (^)(NSError *error))failureBlock;
#endif
+ (void)unregisterTextSecureWithSuccess:(successCompletionBlock)success failure:(failedBlock)failureBlock;
+ (void)unregisterTextSecureWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failureBlock;
@end
NS_ASSUME_NONNULL_END

@ -6,31 +6,52 @@
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSAccountManager.h"
#import "NSData+Base64.h"
#import "NSData+hexString.h"
#import "NSURLSessionDataTask+StatusCode.h"
#import "OWSError.h"
#import "SecurityUtils.h"
#import "TSAccountManager.h"
#import "TSNetworkManager.h"
#import "TSPreKeyManager.h"
#import "TSRedPhoneTokenRequest.h"
#import "TSSocketManager.h"
#import "TSStorageManager+keyingMaterial.h"
NS_ASSUME_NONNULL_BEGIN
@interface TSAccountManager ()
@property (nonatomic, retain) NSString *phoneNumberAwaitingVerification;
@property (nullable, nonatomic, retain) NSString *phoneNumberAwaitingVerification;
@property (nonatomic, strong, readonly) TSNetworkManager *networkManager;
@property (nonatomic, strong, readonly) TSStorageManager *storageManager;
@end
@implementation TSAccountManager
+ (instancetype)sharedInstance {
- (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager
storageManager:(TSStorageManager *)storageManager
{
self = [super init];
if (!self) {
return self;
}
_networkManager = networkManager;
_storageManager = storageManager;
return self;
}
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
static id sharedInstance = nil;
dispatch_once(&onceToken, ^{
sharedInstance = [self.class new];
sharedInstance = [[self alloc] initWithNetworkManager:[TSNetworkManager sharedManager]
storageManager:[TSStorageManager sharedManager]];
});
return sharedInstance;
@ -40,23 +61,25 @@
return [TSStorageManager localNumber] ? YES : NO;
}
+ (void)runIfRegistered:(void (^)())block
- (void)ifRegistered:(BOOL)isRegistered runAsync:(void (^)())block
{
[[TSStorageManager sharedManager] runIfHasLocalNumber:block];
[self.storageManager ifLocalNumberPresent:isRegistered runAsync:block];
}
+ (void)didRegister {
TSAccountManager *sharedManager = [self sharedInstance];
__strong NSString *phoneNumber = sharedManager.phoneNumberAwaitingVerification;
- (void)didRegister
{
DDLogInfo(@"%@ didRegister", self.tag);
NSString *phoneNumber = self.phoneNumberAwaitingVerification;
if (!phoneNumber) {
@throw [NSException exceptionWithName:@"RegistrationFail" reason:@"Internal Corrupted State" userInfo:nil];
}
[TSStorageManager storePhoneNumber:phoneNumber];
[self.storageManager storePhoneNumber:phoneNumber];
}
+ (NSString *)localNumber {
+ (nullable NSString *)localNumber
{
TSAccountManager *sharedManager = [self sharedInstance];
NSString *awaitingVerif = sharedManager.phoneNumberAwaitingVerification;
if (awaitingVerif) {
@ -88,23 +111,26 @@
return registrationID;
}
+ (void)registerForPushNotifications:(NSString *)pushToken
voipToken:(NSString *)voipToken
success:(successCompletionBlock)success
failure:(failedBlock)failureBlock {
[[TSNetworkManager sharedManager]
makeRequest:[[TSRegisterForPushRequest alloc] initWithPushIdentifier:pushToken voipIdentifier:voipToken]
- (void)registerForPushNotificationsWithPushToken:(NSString *)pushToken
voipToken:(NSString *)voipToken
success:(void (^)())successHandler
failure:(void (^)(NSError *))failureHandler
{
TSRegisterForPushRequest *request =
[[TSRegisterForPushRequest alloc] initWithPushIdentifier:pushToken voipIdentifier:voipToken];
[self.networkManager makeRequest:request
success:^(NSURLSessionDataTask *task, id responseObject) {
success();
successHandler();
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
failureBlock(error);
failureHandler(error);
}];
}
+ (void)registerWithPhoneNumber:(NSString *)phoneNumber
success:(successCompletionBlock)successBlock
failure:(failedBlock)failureBlock
success:(void (^)())successBlock
failure:(void (^)(NSError *error))failureBlock
smsVerification:(BOOL)isSMS
{
@ -118,16 +144,22 @@
initWithPhoneNumber:phoneNumber
transport:isSMS ? TSVerificationTransportSMS : TSVerificationTransportVoice]
success:^(NSURLSessionDataTask *task, id responseObject) {
successBlock();
TSAccountManager *manager = [self sharedInstance];
manager.phoneNumberAwaitingVerification = phoneNumber;
DDLogInfo(@"%@ Successfully requested verification code request for number: %@ method:%@",
self.tag,
phoneNumber,
isSMS ? @"SMS" : @"Voice");
TSAccountManager *manager = [self sharedInstance];
manager.phoneNumberAwaitingVerification = phoneNumber;
successBlock();
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
failureBlock(error);
DDLogError(@"%@ Failed to request verification code request with error:%@", self.tag, error);
failureBlock(error);
}];
}
+ (void)rerequestSMSWithSuccess:(successCompletionBlock)successBlock failure:(failedBlock)failureBlock {
+ (void)rerequestSMSWithSuccess:(void (^)())successBlock failure:(void (^)(NSError *error))failureBlock
{
TSAccountManager *manager = [self sharedInstance];
NSString *number = manager.phoneNumberAwaitingVerification;
@ -136,7 +168,8 @@
[self registerWithPhoneNumber:number success:successBlock failure:failureBlock smsVerification:YES];
}
+ (void)rerequestVoiceWithSuccess:(successCompletionBlock)successBlock failure:(failedBlock)failureBlock {
+ (void)rerequestVoiceWithSuccess:(void (^)())successBlock failure:(void (^)(NSError *error))failureBlock
{
TSAccountManager *manager = [self sharedInstance];
NSString *number = manager.phoneNumberAwaitingVerification;
@ -145,18 +178,16 @@
[self registerWithPhoneNumber:number success:successBlock failure:failureBlock smsVerification:NO];
}
+ (void)verifyAccountWithCode:(NSString *)verificationCode
pushToken:(NSString *)pushToken
voipToken:(NSString *)voipToken
success:(successCompletionBlock)successBlock
failure:(failedBlock)failureBlock {
NSString *authToken = [self generateNewAccountAuthenticationToken];
NSString *signalingKey = [self generateNewSignalingKeyToken];
NSString *phoneNumber = ((TSAccountManager *)[self sharedInstance]).phoneNumberAwaitingVerification;
- (void)verifyAccountWithCode:(NSString *)verificationCode
success:(void (^)())successBlock
failure:(void (^)(NSError *error))failureBlock
{
NSString *authToken = [[self class] generateNewAccountAuthenticationToken];
NSString *signalingKey = [[self class] generateNewSignalingKeyToken];
NSString *phoneNumber = self.phoneNumberAwaitingVerification;
assert(signalingKey);
assert(authToken);
assert(pushToken);
assert(phoneNumber);
TSVerifyCodeRequest *request = [[TSVerifyCodeRequest alloc] initWithVerificationCode:verificationCode
@ -164,53 +195,47 @@
signalingKey:signalingKey
authKey:authToken];
[[TSNetworkManager sharedManager] makeRequest:request
[self.networkManager makeRequest:request
success:^(NSURLSessionDataTask *task, id responseObject) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
long statuscode = response.statusCode;
if (statuscode == 200 || statuscode == 204) {
[TSStorageManager storeServerToken:authToken signalingKey:signalingKey];
[self registerForPushNotifications:pushToken
voipToken:voipToken
success:^{
[self registerPreKeys:^{
[TSSocketManager becomeActiveFromForeground];
successBlock();
}
failure:failureBlock];
}
failure:^(NSError *error) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
long statuscode = response.statusCode;
switch (statuscode) {
case 200:
case 204: {
[TSStorageManager storeServerToken:authToken signalingKey:signalingKey];
[self didRegister];
[TSSocketManager becomeActiveFromForeground];
[TSPreKeyManager registerPreKeysWithSuccess:successBlock failure:failureBlock];
break;
}
default: {
DDLogError(@"%@ Unexpected status while verifying code: %ld", self.tag, statuscode);
NSError *error = OWSErrorMakeUnableToProcessServerResponseError();
failureBlock(error);
}];
}
break;
}
}
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogError(@"Error registering with TextSecure: %@", error.debugDescription);
failureBlock(error);
DDLogWarn(@"%@ Error verifying code: %@", self.tag, error.debugDescription);
switch (error.code) {
case 403: {
NSError *userError = OWSErrorWithCodeDescription(OWSErrorCodeUserError,
NSLocalizedString(@"REGISTRATION_VERIFICATION_FAILED_WRONG_CODE_DESCRIPTION",
"Alert body, during registration"));
failureBlock(userError);
break;
}
default: {
DDLogError(@"%@ verifying code failed with unhandled error: %@", self.tag, error);
failureBlock(error);
break;
}
}
}];
}
+ (void)registerPreKeysAfterPush:(NSString *)pushToken
voipToken:(NSString *)voipToken
success:(successCompletionBlock)successBlock
failure:(failedBlock)failureBlock {
[self registerForPushNotifications:pushToken
voipToken:voipToken
success:^{
[self registerPreKeys:successBlock failure:failureBlock];
}
failure:failureBlock];
}
+ (void)registerPreKeys:(successCompletionBlock)successBlock failure:(failedBlock)failureBlock {
[TSPreKeyManager registerPreKeysWithSuccess:^{
successBlock();
}
failure:failureBlock];
}
#pragma mark Server keying material
+ (NSString *)generateNewAccountAuthenticationToken {
@ -228,24 +253,45 @@
return signalingKeyTokenPrint;
}
+ (void)obtainRPRegistrationToken:(void (^)(NSString *rpRegistrationToken))success failure:(failedBlock)failureBlock {
[[TSNetworkManager sharedManager] makeRequest:[[TSRedPhoneTokenRequest alloc] init]
- (void)obtainRPRegistrationTokenWithSuccess:(void (^)(NSString *rpRegistrationToken))success
failure:(void (^)(NSError *error))failureBlock
{
[self.networkManager makeRequest:[[TSRedPhoneTokenRequest alloc] init]
success:^(NSURLSessionDataTask *task, id responseObject) {
success([responseObject objectForKey:@"token"]);
DDLogInfo(@"%@ Successfully obtained Redphone token", self.tag);
success([responseObject objectForKey:@"token"]);
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
failureBlock(error);
DDLogError(@"%@ Failed to obtain Redphone token with error: %@", self.tag, error);
failureBlock(error);
}];
}
+ (void)unregisterTextSecureWithSuccess:(successCompletionBlock)success failure:(failedBlock)failureBlock {
+ (void)unregisterTextSecureWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failureBlock
{
[[TSNetworkManager sharedManager] makeRequest:[[TSUnregisterAccountRequest alloc] init]
success:^(NSURLSessionDataTask *task, id responseObject) {
success();
DDLogInfo(@"%@ Successfully unregistered", self.tag);
success();
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
failureBlock(error);
DDLogError(@"%@ Failed to unregister with error: %@", self.tag, error);
failureBlock(error);
}];
}
#pragma mark - Logging
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
}
@end
NS_ASSUME_NONNULL_END

@ -8,14 +8,13 @@
#import <Foundation/Foundation.h>
#import "TSAccountManager.h"
#import "TSConstants.h"
// Time before deletion of signed PreKeys (measured in seconds)
#define SignedPreKeysDeletionTime 14 * 24 * 60 * 60
@interface TSPreKeyManager : NSObject
+ (void)registerPreKeysWithSuccess:(successCompletionBlock)success failure:(failedBlock)failureBlock;
+ (void)registerPreKeysWithSuccess:(void (^)())successHandler failure:(void (^)(NSError *error))failureHandler;
+ (void)refreshPreKeys;

@ -16,7 +16,8 @@
@implementation TSPreKeyManager
+ (void)registerPreKeysWithSuccess:(successCompletionBlock)success failure:(failedBlock)failureBlock {
+ (void)registerPreKeysWithSuccess:(void (^)())success failure:(void (^)(NSError *))failureBlock
{
TSStorageManager *storageManager = [TSStorageManager sharedManager];
ECKeyPair *identityKeyPair = [storageManager identityKeyPair];
@ -38,13 +39,15 @@
[[TSNetworkManager sharedManager] makeRequest:request
success:^(NSURLSessionDataTask *task, id responseObject) {
[storageManager storePreKeyRecords:preKeys];
[storageManager storeSignedPreKey:signedPreKey.Id signedPreKeyRecord:signedPreKey];
DDLogInfo(@"%@ Successfully registered pre keys.", self.tag);
[storageManager storePreKeyRecords:preKeys];
[storageManager storeSignedPreKey:signedPreKey.Id signedPreKeyRecord:signedPreKey];
success();
success();
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
failureBlock(error);
DDLogError(@"%@ Failed to register pre keys.", self.tag);
failureBlock(error);
}];
}
@ -123,4 +126,16 @@
return oldRecords;
}
#pragma mark - Logging
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
}
@end

@ -214,7 +214,7 @@ static NSString *const OWSDisappearingMessageFinderExpiresAtIndex = @"index_mess
withName:OWSDisappearingMessageFinderExpiresAtIndex
completionBlock:^(BOOL ready) {
if (ready) {
DDLogInfo(@"%@ completed registering extension async.", self.tag);
DDLogDebug(@"%@ completed registering extension async.", self.tag);
} else {
DDLogError(@"%@ failed registering extension async.", self.tag);
}

@ -634,7 +634,7 @@ NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceExceptio
if (![storage containsSession:identifier deviceId:[deviceNumber intValue]]) {
__block dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block PreKeyBundle *bundle;
__block NSException *exception;
[self.networkManager makeRequest:[[TSRecipientPrekeyRequest alloc] initWithRecipient:identifier
deviceId:[deviceNumber stringValue]]
success:^(NSURLSessionDataTask *task, id responseObject) {
@ -645,13 +645,17 @@ NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceExceptio
DDLogError(@"Server replied on PreKeyBundle request with error: %@", error);
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
if (response.statusCode == 404) {
@throw [NSException exceptionWithName:OWSMessageSenderInvalidDeviceException
reason:@"Device not registered"
userInfo:nil];
// Can't throw exception from within callback as it's probabably a different thread.
exception = [NSException exceptionWithName:OWSMessageSenderInvalidDeviceException
reason:@"Device not registered"
userInfo:nil];
}
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
if (exception) {
@throw exception;
}
if (!bundle) {
@throw [NSException exceptionWithName:InvalidVersionException

@ -35,10 +35,11 @@
*/
- (NSString *)localNumber;
+ (NSString *)localNumber;
- (void)runIfHasLocalNumber:(void (^)())block;
- (void)ifLocalNumberPresent:(BOOL)isPresent runAsync:(void (^)())block;
+ (void)storeServerToken:(NSString *)authToken signalingKey:(NSString *)signalingKey;
+ (void)storePhoneNumber:(NSString *)phoneNumber;
- (void)storePhoneNumber:(NSString *)phoneNumber;
@end

@ -20,15 +20,30 @@
return [self stringForKey:TSStorageRegisteredNumberKey inCollection:TSStorageUserAccountCollection];
}
- (void)runIfHasLocalNumber:(void (^)())block
- (void)ifLocalNumberPresent:(BOOL)runIfPresent runAsync:(void (^)())block;
{
[self.newDatabaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
if ([transaction objectForKey:TSStorageRegisteredNumberKey inCollection:TSStorageUserAccountCollection]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__block BOOL isPresent;
[self.newDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
isPresent = [[transaction objectForKey:TSStorageRegisteredNumberKey
inCollection:TSStorageUserAccountCollection] boolValue];
}];
if (isPresent == runIfPresent) {
if (runIfPresent) {
DDLogDebug(@"%@ Running existing-user block", self.logTag);
} else {
DDLogDebug(@"%@ Running new-user block", self.logTag);
}
block();
} else {
DDLogDebug(@"%@ Skipping block since no local number is registered", self.logTag);
if (runIfPresent) {
DDLogDebug(@"%@ Skipping existing-user block for new-user", self.logTag);
} else {
DDLogDebug(@"%@ Skipping new-user block for existing-user", self.logTag);
}
}
}];
});
}
+ (NSString *)signalingKey {
@ -39,13 +54,12 @@
return [[self sharedManager] stringForKey:TSStorageServerAuthToken inCollection:TSStorageUserAccountCollection];
}
+ (void)storePhoneNumber:(NSString *)phoneNumber {
YapDatabaseConnection *dbConn = [[self sharedManager] dbConnection];
[dbConn readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:phoneNumber
forKey:TSStorageRegisteredNumberKey
inCollection:TSStorageUserAccountCollection];
- (void)storePhoneNumber:(NSString *)phoneNumber
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:phoneNumber
forKey:TSStorageRegisteredNumberKey
inCollection:TSStorageUserAccountCollection];
}];
}

@ -40,10 +40,6 @@ typedef enum { kSMSVerification, kPhoneNumberVerification } VerificationTranspor
#define textSecureDeviceProvisioningAPIFormat @"v1/provisioning/%@"
#define textSecureDevicesAPIFormat @"v1/devices/%@"
typedef void (^successCompletionBlock)(void);
typedef void (^failedRegistrationRequestBlock)(void);
#pragma mark Push RegistrationSpecific Constants
typedef NS_ENUM(NSInteger, TSPushRegistrationError) {
TSPushRegistrationErrorNetwork,

@ -13,7 +13,8 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) {
OWSErrorCodePrivacyVerificationFailure = 20,
OWSErrorCodeUntrustedIdentityKey = 25,
OWSErrorCodeFailedToSendOutgoingMessage = 30,
OWSErrorCodeFailedToDecryptMessage = 100
OWSErrorCodeFailedToDecryptMessage = 100,
OWSErrorCodeUserError = 2001,
};
extern NSError *OWSErrorWithCodeDescription(OWSErrorCode code, NSString *description);

@ -7,39 +7,41 @@
@interface SignalRecipientTest : XCTestCase
@property (nonatomic) NSString *localNumber;
@end
@implementation SignalRecipientTest
- (void)setUp {
- (void)setUp
{
[super setUp];
[TSStorageManager storePhoneNumber:@"+13231231234"];
self.localNumber = @"+13231231234";
[[TSStorageManager sharedManager] storePhoneNumber:self.localNumber];
}
- (void)testSelfRecipientWithExistingRecord
{
// Sanity Check
NSString *localNumber = @"+13231231234";
XCTAssertNotNil(localNumber);
[[[SignalRecipient alloc] initWithTextSecureIdentifier:localNumber relay:nil supportsVoice:YES] save];
XCTAssertNotNil([SignalRecipient recipientWithTextSecureIdentifier:localNumber]);
XCTAssertNotNil(self.localNumber);
[[[SignalRecipient alloc] initWithTextSecureIdentifier:self.localNumber relay:nil supportsVoice:YES] save];
XCTAssertNotNil([SignalRecipient recipientWithTextSecureIdentifier:self.localNumber]);
SignalRecipient *me = [SignalRecipient selfRecipient];
XCTAssert(me);
XCTAssertEqualObjects(localNumber, me.uniqueId);
XCTAssertEqualObjects(self.localNumber, me.uniqueId);
}
- (void)testSelfRecipientWithoutExistingRecord
{
NSString *localNumber = @"+13231231234";
XCTAssertNotNil(localNumber);
[[SignalRecipient fetchObjectWithUniqueID:localNumber] remove];
XCTAssertNotNil(self.localNumber);
[[SignalRecipient fetchObjectWithUniqueID:self.localNumber] remove];
// Sanity Check that there's no existing user.
XCTAssertNil([SignalRecipient recipientWithTextSecureIdentifier:localNumber]);
XCTAssertNil([SignalRecipient recipientWithTextSecureIdentifier:self.localNumber]);
SignalRecipient *me = [SignalRecipient selfRecipient];
XCTAssert(me);
XCTAssertEqualObjects(localNumber, me.uniqueId);
XCTAssertEqualObjects(self.localNumber, me.uniqueId);
}
@end

@ -188,7 +188,7 @@ NS_ASSUME_NONNULL_BEGIN
[super setUp];
// Hack to make sure we don't explode when sending sync message.
[TSStorageManager storePhoneNumber:@"+13231231234"];
[[TSStorageManager sharedManager] storePhoneNumber:@"+13231231234"];
self.thread = [[TSContactThread alloc] initWithUniqueId:@"fake-thread-id"];
[self.thread save];

Loading…
Cancel
Save