Handle group keychange error (#50)

// FREEBIE
pull/1/head
Michael Kirk 9 years ago committed by GitHub
parent 4ba1e86ec1
commit 31bd1d07a3

@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong) TSGroupModel *groupModel;
+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel;
+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel
transaction:(YapDatabaseReadWriteTransaction *)transaction;

@ -5,6 +5,7 @@
#import "NSData+Base64.h"
#import "SignalRecipient.h"
#import "TSAttachmentStream.h"
#import <YapDatabase/YapDatabaseConnection.h>
#import <YapDatabase/YapDatabaseTransaction.h>
NS_ASSUME_NONNULL_BEGIN
@ -65,6 +66,15 @@ NS_ASSUME_NONNULL_BEGIN
return thread;
}
+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel
{
__block TSGroupThread *thread;
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [self getOrCreateThreadWithGroupModel:groupModel transaction:transaction];
}];
return thread;
}
+ (NSString *)threadIdFromGroupId:(NSData *)groupId
{
return [TSGroupThreadPrefix stringByAppendingString:[groupId base64EncodedString]];

@ -348,16 +348,28 @@ NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceExceptio
}];
[completionFuture catchDo:^(id failure) {
if ([failure isKindOfClass:[NSError class]]) {
return failureHandler(failure);
} else if ([failure isKindOfClass:[NSArray class]]) {
// failure from toc_thenAll yeilds an array of failed Futures, rather than the future's failure.
if ([failure isKindOfClass:[NSArray class]]) {
NSArray *errors = (NSArray *)failure;
// failure from toc_thenAll is a Future, rather than the future's failure.
if ([errors.lastObject isKindOfClass:[TOCFuture class]]) {
TOCFuture *lastFailure = (TOCFuture *)errors.lastObject;
id failureResult = lastFailure.forceGetFailure;
if ([failureResult isKindOfClass:[NSError class]]) {
return failureHandler((NSError *)failureResult);
for (TOCFuture *failedFuture in errors) {
if (!failedFuture.hasFailed) {
// If at least one send succeeded, don't show message as failed.
// Else user will tap-to-resend to all recipients, including those that already received the
// message.
return successHandler();
}
}
// At this point, all recipients must have failed.
// But we have all this verbose type checking because TOCFuture doesn't expose type information.
id lastError = errors.lastObject;
if ([lastError isKindOfClass:[TOCFuture class]]) {
TOCFuture *failedFuture = (TOCFuture *)lastError;
if (failedFuture.hasFailed) {
id failureResult = failedFuture.forceGetFailure;
if ([failureResult isKindOfClass:[NSError class]]) {
return failureHandler((NSError *)failureResult);
}
}
}
}
@ -426,8 +438,17 @@ NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceExceptio
void (^retrySend)() = ^void() {
if (remainingAttempts <= 0) {
return failureHandler(error);
NSError *presentedError = error;
if (statuscode == 409) {
presentedError = OWSErrorWithCodeDescription(OWSErrorCodeUntrustedIdentityKey,
NSLocalizedString(@"FAILED_SENDING_BECAUSE_UNTRUSTED_IDENTITY_KEY",
@"action sheet header when re-sending message which failed because of untrusted "
@"identity keys"));
}
return failureHandler(presentedError);
}
dispatch_async([OWSDispatch sendingQueue], ^{
[self sendMessage:message
recipient:recipient

@ -11,6 +11,7 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) {
OWSErrorCodeFailedToEncodeJson = 14,
OWSErrorCodeFailedToDecodeQR = 15,
OWSErrorCodePrivacyVerificationFailure = 20,
OWSErrorCodeUntrustedIdentityKey = 25,
OWSErrorCodeFailedToSendOutgoingMessage = 30,
OWSErrorCodeFailedToDecryptMessage = 100
};

@ -1,6 +1,7 @@
// Created by Michael Kirk on 10/7/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "Cryptography.h"
#import "OWSError.h"
#import "OWSFakeContactsManager.h"
#import "OWSFakeContactsUpdater.h"
@ -8,11 +9,15 @@
#import "OWSMessageSender.h"
#import "OWSUploadingService.h"
#import "TSContactThread.h"
#import "TSGroupModel.h"
#import "TSGroupThread.h"
#import "TSMessagesManager.h"
#import "TSNetworkManager.h"
#import "TSOutgoingMessage.h"
#import "TSStorageManager+keyingMaterial.h"
#import "TSStorageManager.h"
#import <AxolotlKit/AxolotlExceptions.h>
#import <AxolotlKit/SessionBuilder.h>
#import <XCTest/XCTest.h>
NS_ASSUME_NONNULL_BEGIN
@ -393,6 +398,44 @@ NS_ASSUME_NONNULL_BEGIN
[self waitForExpectationsWithTimeout:5 handler:nil];
}
- (void)testGroupSend
{
OWSMessageSender *messageSender = self.successfulMessageSender;
NSData *groupIdData = [Cryptography generateRandomBytes:32];
SignalRecipient *successfulRecipient =
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id" relay:nil supportsVoice:YES];
SignalRecipient *successfulRecipient2 =
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id2" relay:nil supportsVoice:YES];
TSGroupModel *groupModel = [[TSGroupModel alloc]
initWithTitle:@"group title"
memberIds:[@[ successfulRecipient.uniqueId, successfulRecipient2.uniqueId ] mutableCopy]
image:nil
groupId:groupIdData];
TSGroupThread *groupThread = [TSGroupThread getOrCreateThreadWithGroupModel:groupModel];
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:1
inThread:groupThread
messageBody:@"We want punks in the palace."];
XCTestExpectation *markedAsSent = [self expectationWithDescription:@"markedAsSent"];
[messageSender sendMessage:message
success:^{
if (message.messageState == TSOutgoingMessageStateSent) {
[markedAsSent fulfill];
} else {
XCTFail(@"Unexpected message state");
}
}
failure:^(NSError *_Nonnull error) {
XCTFail(@"sendMessage should not fail.");
}];
[self waitForExpectationsWithTimeout:5 handler:nil];
}
- (void)testGetRecipients
{
SignalRecipient *recipient =

Loading…
Cancel
Save