Fix closed group and contact syncing.

This commit is contained in:
Mikunj 2020-05-06 13:24:38 +10:00
parent 5060f82a68
commit 9fc386b803
6 changed files with 46 additions and 19 deletions

View File

@ -62,10 +62,10 @@ typedef NS_ENUM(NSInteger, LKFriendRequestStatus) {
# pragma mark - Friend Requests
- (NSSet<NSString *> *)getAllFriendsWithTransaction:(YapDatabaseReadTransaction *)transaction NS_SWIFT_NAME(getAllFriends(using:));
- (LKFriendRequestStatus)getFriendRequestStatusForContact:(NSString *)hexEncodedPublicKey transaction:(YapDatabaseReadTransaction *)transaction NS_SWIFT_NAME(getFriendRequestStatus(for:transaction:));
- (void)setFriendRequestStatus:(LKFriendRequestStatus)friendRequestStatus forContact:(NSString *)hexEncodedPublicKey transaction:(YapDatabaseReadWriteTransaction *)transaction NS_SWIFT_NAME(setFriendRequestStatus(_:for:transaction:));
@end
NS_ASSUME_NONNULL_END

View File

@ -226,6 +226,16 @@
#define LKFriendRequestCollection @"LKFriendRequestCollection"
- (NSSet<NSString *> *)getAllFriendsWithTransaction:(YapDatabaseReadTransaction *)transaction {
NSMutableSet<NSString *> *hexEncodedPublicKeys = [NSMutableSet set];
[transaction enumerateKeysAndObjectsInCollection:LKFriendRequestCollection usingBlock:^(NSString *hexEncodedPublicKey, NSNumber *status, BOOL * _Nonnull stop) {
if ([status integerValue] == LKFriendRequestStatusFriends) {
[hexEncodedPublicKeys addObject:hexEncodedPublicKey];
}
}];
return hexEncodedPublicKeys;
}
- (LKFriendRequestStatus)getFriendRequestStatusForContact:(NSString *)hexEncodedPublicKey transaction:(YapDatabaseReadTransaction *)transaction {
NSNumber *_Nullable status = [transaction objectForKey:hexEncodedPublicKey inCollection:LKFriendRequestCollection];
if (status == nil) { return LKFriendRequestStatusNone; }

View File

@ -170,6 +170,8 @@ public final class FriendRequestProtocol : NSObject {
@objc(shouldUpdateFriendRequestStatusFromMessage:)
public static func shouldUpdateFriendRequestStatus(from message: TSOutgoingMessage) -> Bool {
// The order of these checks matters
if (message.thread.isGroupThread()) { return false }
if (message.thread.contactIdentifier() == getUserHexEncodedPublicKey()) { return false }
if (message as? DeviceLinkMessage)?.kind == .request { return true }
if message is SessionRequestMessage { return false }
return message is FriendRequestMessage
@ -243,7 +245,7 @@ public final class FriendRequestProtocol : NSObject {
// Signal cipher decryption and thus that we have a session with the other person.
let friendRequestStatus = storage.getFriendRequestStatus(for: hexEncodedPublicKey, transaction: transaction);
// We shouldn't be able to skip from none to friends
guard friendRequestStatus != .none else { return }
guard friendRequestStatus != .none && friendRequestStatus != .friends else { return }
// Become friends
storage.setFriendRequestStatus(.friends, for: hexEncodedPublicKey, transaction: transaction)
// Send a contact sync message if needed

View File

@ -622,6 +622,7 @@ class FriendRequestProtocolTests : XCTestCase {
}
// MARK: - shouldUpdateFriendRequestStatus
func test_shouldUpdateFriendRequestStatusReturnsTheCorrectValue() {
let thread = LokiTestUtilities.createContactThread(for: LokiTestUtilities.generateHexEncodedPublicKey())
@ -637,4 +638,19 @@ class FriendRequestProtocolTests : XCTestCase {
XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: sessionRequest))
XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: deviceLinkAuthorisation))
}
func test_shouldUpdateFriendRequestStatusReturnsFalseForGroupThreads() {
let allGroupTypes: [GroupType] = [ .closedGroup, .openGroup, .rssFeed ]
for groupType in allGroupTypes {
guard let groupThread = LokiTestUtilities.createGroupThread(groupType: groupType) else { return XCTFail() }
let friendRequest = FriendRequestMessage(timestamp: 1, thread: groupThread, body: "")
XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: friendRequest))
}
}
func test_shouldUpdateFriendRequestStatusReturnsFalseForCurrentDevice() {
let thread = LokiTestUtilities.createContactThread(for: LokiTestUtilities.getCurrentUserHexEncodedPublicKey())
let friendRequest = FriendRequestMessage(timestamp: 1, thread: thread, body: "")
XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: friendRequest))
}
}

View File

@ -36,22 +36,16 @@ public final class SyncMessagesProtocol : NSObject {
}
public static func syncAllContacts() -> Promise<Void> {
// Collect all master devices with which a session has been established. Note that
// this is not the same as all master devices with which we're friends.
var hepks: Set<String> = []
TSContactThread.enumerateCollectionObjects { object, _ in
guard let thread = object as? TSContactThread else { return }
let hexEncodedPublicKey = thread.contactIdentifier()
guard thread.isContactFriend && thread.shouldThreadBeVisible && !thread.isSlaveThread else { return }
hepks.insert(hexEncodedPublicKey)
// We need to sync over all contacts whom we are friends with.
var hepks: [String] = []
storage.dbReadConnection.read { transaction in
hepks = self.storage
.getAllFriends(using: transaction)
.filter { ECKeyPair.isValidHexEncodedPublicKey(candidate: $0) }
.map { storage.getMasterHexEncodedPublicKey(for: $0, in: transaction) ?? $0 }
}
TSGroupThread.enumerateCollectionObjects { object, _ in
guard let group = object as? TSGroupThread, group.groupModel.groupType == .closedGroup,
group.shouldThreadBeVisible else { return }
hepks.formUnion(group.groupModel.groupMemberIds)
}
hepks.insert(getUserHexEncodedPublicKey()) // TODO: Are we sure about this?
let friends = hepks.map { SignalAccount(recipientId: $0) }
let friends = Set(hepks).map { SignalAccount(recipientId: $0) }
let syncManager = SSKEnvironment.shared.syncManager
let promises = friends.chunked(by: 3).map { friends -> Promise<Void> in // TODO: Does this always fit?
return Promise(syncManager.syncContacts(for: friends)).map { _ in }
@ -172,10 +166,10 @@ public final class SyncMessagesProtocol : NSObject {
public static func handleContactSyncMessageData(_ data: Data, using transaction: YapDatabaseReadWriteTransaction) {
let parser = ContactParser(data: data)
let hexEncodedPublicKeys = parser.parseHexEncodedPublicKeys()
let linkedDevices = LokiDatabaseUtilities.getLinkedDeviceHexEncodedPublicKeys(for: getUserHexEncodedPublicKey(), in: transaction)
let ourHexEncodedPublicKey = getUserHexEncodedPublicKey()
// Try to establish sessions
for hexEncodedPublicKey in hexEncodedPublicKeys {
guard !linkedDevices.contains(hexEncodedPublicKey) else { continue } // Skip self
guard hexEncodedPublicKey != ourHexEncodedPublicKey else { continue } // Skip self
// We don't update the friend request status; that's done in OWSMessageSender.sendMessage(_:)
let friendRequestStatus = storage.getFriendRequestStatus(for: hexEncodedPublicKey, transaction: transaction)
switch friendRequestStatus {

View File

@ -383,6 +383,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[allAttachmentIds
addObjectsFromArray:[OutgoingMessagePreparer prepareMessageForSending:message transaction:transaction]];
// Loki - Optimistically update friend request status when we can
if ([LKFriendRequestProtocol shouldUpdateFriendRequestStatusFromMessage:message]) {
[LKFriendRequestProtocol setFriendRequestStatusToSendingIfNeededForHexEncodedPublicKey:message.thread.contactIdentifier transaction:transaction];
}
}];
NSOperationQueue *sendingQueue = [self sendingQueueForMessage:message];