Merge branch 'dev' into closed-group-editing

pull/280/head
nielsandriesse 5 years ago
commit e789ac12e6

@ -4143,7 +4143,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 116; CURRENT_PROJECT_VERSION = 118;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = SUQ8J2PCT7; DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -4205,7 +4205,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 116; CURRENT_PROJECT_VERSION = 118;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7; DEVELOPMENT_TEAM = SUQ8J2PCT7;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
@ -4259,7 +4259,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 116; CURRENT_PROJECT_VERSION = 118;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = SUQ8J2PCT7; DEVELOPMENT_TEAM = SUQ8J2PCT7;
@ -4329,7 +4329,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 116; CURRENT_PROJECT_VERSION = 118;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = SUQ8J2PCT7; DEVELOPMENT_TEAM = SUQ8J2PCT7;
@ -4391,7 +4391,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 116; CURRENT_PROJECT_VERSION = 118;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = SUQ8J2PCT7; DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -4454,7 +4454,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 116; CURRENT_PROJECT_VERSION = 118;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7; DEVELOPMENT_TEAM = SUQ8J2PCT7;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
@ -4655,7 +4655,7 @@
CODE_SIGN_ENTITLEMENTS = Signal/Signal.entitlements; CODE_SIGN_ENTITLEMENTS = Signal/Signal.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 116; CURRENT_PROJECT_VERSION = 118;
DEVELOPMENT_TEAM = SUQ8J2PCT7; DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -4722,7 +4722,7 @@
CODE_SIGN_ENTITLEMENTS = Signal/Signal.entitlements; CODE_SIGN_ENTITLEMENTS = Signal/Signal.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 116; CURRENT_PROJECT_VERSION = 118;
DEVELOPMENT_TEAM = SUQ8J2PCT7; DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",

@ -243,25 +243,20 @@ public final class SnodeAPI : NSObject {
internal static func parseRawMessagesResponse(_ rawResponse: Any, from snode: Snode, associatedWith publicKey: String) -> [SSKProtoEnvelope] { internal static func parseRawMessagesResponse(_ rawResponse: Any, from snode: Snode, associatedWith publicKey: String) -> [SSKProtoEnvelope] {
guard let json = rawResponse as? JSON, let rawMessages = json["messages"] as? [JSON] else { return [] } guard let json = rawResponse as? JSON, let rawMessages = json["messages"] as? [JSON] else { return [] }
if let (lastHash, expirationDate) = updateLastMessageHashValueIfPossible(for: snode, associatedWith: publicKey, from: rawMessages), updateLastMessageHashValueIfPossible(for: snode, associatedWith: publicKey, from: rawMessages)
UserDefaults.standard[.isUsingFullAPNs] {
LokiPushNotificationManager.acknowledgeDelivery(forMessageWithHash: lastHash, expiration: expirationDate, publicKey: getUserHexEncodedPublicKey())
}
let rawNewMessages = removeDuplicates(from: rawMessages, associatedWith: publicKey) let rawNewMessages = removeDuplicates(from: rawMessages, associatedWith: publicKey)
let newMessages = parseProtoEnvelopes(from: rawNewMessages) let newMessages = parseProtoEnvelopes(from: rawNewMessages)
return newMessages return newMessages
} }
private static func updateLastMessageHashValueIfPossible(for snode: Snode, associatedWith publicKey: String, from rawMessages: [JSON]) -> (String, UInt64)? { private static func updateLastMessageHashValueIfPossible(for snode: Snode, associatedWith publicKey: String, from rawMessages: [JSON]) {
if let lastMessage = rawMessages.last, let lastHash = lastMessage["hash"] as? String, let expirationDate = lastMessage["expiration"] as? UInt64 { if let lastMessage = rawMessages.last, let lastHash = lastMessage["hash"] as? String, let expirationDate = lastMessage["expiration"] as? UInt64 {
try! Storage.writeSync { transaction in try! Storage.writeSync { transaction in
Storage.setLastMessageHashInfo(for: snode, associatedWith: publicKey, to: [ "hash" : lastHash, "expirationDate" : NSNumber(value: expirationDate) ], using: transaction) Storage.setLastMessageHashInfo(for: snode, associatedWith: publicKey, to: [ "hash" : lastHash, "expirationDate" : NSNumber(value: expirationDate) ], using: transaction)
} }
return (lastHash, expirationDate)
} else if (!rawMessages.isEmpty) { } else if (!rawMessages.isEmpty) {
print("[Loki] Failed to update last message hash value from: \(rawMessages).") print("[Loki] Failed to update last message hash value from: \(rawMessages).")
} }
return nil
} }
private static func removeDuplicates(from rawMessages: [JSON], associatedWith publicKey: String) -> [JSON] { private static func removeDuplicates(from rawMessages: [JSON], associatedWith publicKey: String) -> [JSON] {

@ -235,8 +235,8 @@ public final class ClosedGroupsProtocol : NSObject {
private static func isValid(_ closedGroupUpdate: SSKProtoDataMessageClosedGroupUpdate) -> Bool { private static func isValid(_ closedGroupUpdate: SSKProtoDataMessageClosedGroupUpdate) -> Bool {
guard !closedGroupUpdate.groupPublicKey.isEmpty else { return false } guard !closedGroupUpdate.groupPublicKey.isEmpty else { return false }
switch closedGroupUpdate.type { switch closedGroupUpdate.type {
case .new: return !(closedGroupUpdate.name ?? "").isEmpty && !(closedGroupUpdate.groupPrivateKey ?? Data()).isEmpty && !closedGroupUpdate.senderKeys.isEmpty case .new: return !(closedGroupUpdate.name ?? "").isEmpty && !(closedGroupUpdate.groupPrivateKey ?? Data()).isEmpty && !closedGroupUpdate.members.isEmpty
&& !closedGroupUpdate.members.isEmpty && !closedGroupUpdate.admins.isEmpty && !closedGroupUpdate.admins.isEmpty // senderKeys may be empty
case .info: return !(closedGroupUpdate.name ?? "").isEmpty && !closedGroupUpdate.members.isEmpty && !closedGroupUpdate.admins.isEmpty // senderKeys may be empty case .info: return !(closedGroupUpdate.name ?? "").isEmpty && !closedGroupUpdate.members.isEmpty && !closedGroupUpdate.admins.isEmpty // senderKeys may be empty
case .senderKeyRequest: return true case .senderKeyRequest: return true
case .senderKey: return !closedGroupUpdate.senderKeys.isEmpty case .senderKey: return !closedGroupUpdate.senderKeys.isEmpty
@ -244,6 +244,7 @@ public final class ClosedGroupsProtocol : NSObject {
} }
private static func handleNewGroupMessage(_ closedGroupUpdate: SSKProtoDataMessageClosedGroupUpdate, using transaction: YapDatabaseReadWriteTransaction) { private static func handleNewGroupMessage(_ closedGroupUpdate: SSKProtoDataMessageClosedGroupUpdate, using transaction: YapDatabaseReadWriteTransaction) {
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
// Unwrap the message // Unwrap the message
let groupPublicKey = closedGroupUpdate.groupPublicKey.toHexString() let groupPublicKey = closedGroupUpdate.groupPublicKey.toHexString()
let name = closedGroupUpdate.name let name = closedGroupUpdate.name
@ -257,6 +258,25 @@ public final class ClosedGroupsProtocol : NSObject {
let ratchet = ClosedGroupRatchet(chainKey: senderKey.chainKey.toHexString(), keyIndex: UInt(senderKey.keyIndex), messageKeys: []) let ratchet = ClosedGroupRatchet(chainKey: senderKey.chainKey.toHexString(), keyIndex: UInt(senderKey.keyIndex), messageKeys: [])
Storage.setClosedGroupRatchet(for: groupPublicKey, senderPublicKey: senderKey.publicKey.toHexString(), ratchet: ratchet, using: transaction) Storage.setClosedGroupRatchet(for: groupPublicKey, senderPublicKey: senderKey.publicKey.toHexString(), ratchet: ratchet, using: transaction)
} }
// Sort out any discrepancies between the provided sender keys and what's required
let missingSenderKeys = Set(members).subtracting(senderKeys.map { $0.publicKey.toHexString() })
let userPublicKey = getUserHexEncodedPublicKey()
if missingSenderKeys.contains(userPublicKey) {
establishSessionsIfNeeded(with: [String](missingSenderKeys), using: transaction)
let userRatchet = SharedSenderKeysImplementation.shared.generateRatchet(for: groupPublicKey, senderPublicKey: userPublicKey, using: transaction)
let userSenderKey = ClosedGroupSenderKey(chainKey: Data(hex: userRatchet.chainKey), keyIndex: userRatchet.keyIndex, publicKey: Data(hex: userPublicKey))
for member in members {
guard member != userPublicKey else { continue }
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction)
}
}
for publicKey in missingSenderKeys.subtracting([ userPublicKey ]) {
requestSenderKey(for: groupPublicKey, senderPublicKey: publicKey, using: transaction)
}
// Create the group // Create the group
let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey) let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey)
let group = TSGroupModel(title: name, memberIds: members, image: nil, groupId: groupID, groupType: .closedGroup, adminIds: admins) let group = TSGroupModel(title: name, memberIds: members, image: nil, groupId: groupID, groupType: .closedGroup, adminIds: admins)
@ -293,7 +313,7 @@ public final class ClosedGroupsProtocol : NSObject {
} }
let group = thread.groupModel let group = thread.groupModel
// Check that the sender is a member of the group (before the update) // Check that the sender is a member of the group (before the update)
var membersAndLinkedDevices: Set<String> = Set(members) var membersAndLinkedDevices: Set<String> = Set(group.groupMemberIds)
for member in group.groupMemberIds { for member in group.groupMemberIds {
let deviceLinks = OWSPrimaryStorage.shared().getDeviceLinks(for: member, in: transaction) let deviceLinks = OWSPrimaryStorage.shared().getDeviceLinks(for: member, in: transaction)
membersAndLinkedDevices.formUnion(deviceLinks.flatMap { [ $0.master.publicKey, $0.slave.publicKey ] }) membersAndLinkedDevices.formUnion(deviceLinks.flatMap { [ $0.master.publicKey, $0.slave.publicKey ] })

@ -66,7 +66,7 @@ public final class SharedSenderKeysImplementation : NSObject {
let nextMessageKey = try HMAC(key: Data(hex: ratchet.chainKey).bytes, variant: .sha256).authenticate([ UInt8(1) ]) let nextMessageKey = try HMAC(key: Data(hex: ratchet.chainKey).bytes, variant: .sha256).authenticate([ UInt8(1) ])
let nextChainKey = try HMAC(key: Data(hex: ratchet.chainKey).bytes, variant: .sha256).authenticate([ UInt8(2) ]) let nextChainKey = try HMAC(key: Data(hex: ratchet.chainKey).bytes, variant: .sha256).authenticate([ UInt8(2) ])
let nextKeyIndex = ratchet.keyIndex + 1 let nextKeyIndex = ratchet.keyIndex + 1
return ClosedGroupRatchet(chainKey: nextChainKey.toHexString(), keyIndex: nextKeyIndex, messageKeys: ratchet.messageKeys + [ nextMessageKey.toHexString() ]) return ClosedGroupRatchet(chainKey: nextChainKey.toHexString(), keyIndex: nextKeyIndex, messageKeys: [ nextMessageKey.toHexString() ])
} }
/// - Note: Sync. Don't call from the main thread. /// - Note: Sync. Don't call from the main thread.

@ -143,21 +143,4 @@ public final class LokiPushNotificationManager : NSObject {
static func objc_notify(for signalMessage: SignalMessage) -> AnyPromise { static func objc_notify(for signalMessage: SignalMessage) -> AnyPromise {
return AnyPromise.from(notify(for: signalMessage)) return AnyPromise.from(notify(for: signalMessage))
} }
static func acknowledgeDelivery(forMessageWithHash hash: String, expiration: UInt64, publicKey: String) {
let parameters: JSON = [ "lastHash" : hash, "pubKey" : publicKey, "expiration" : expiration]
let url = URL(string: "\(server)/acknowledge_message_delivery")!
let request = TSRequest(url: url, method: "POST", parameters: parameters)
request.allHTTPHeaderFields = [ "Content-Type" : "application/json" ]
TSNetworkManager.shared().makeRequest(request, success: { _, response in
guard let json = response as? JSON else {
return print("[Loki] Couldn't acknowledge delivery for message with hash: \(hash).")
}
guard json["code"] as? Int != 0 else {
return print("[Loki] Couldn't acknowledge delivery for message with hash: \(hash) due to error: \(json["message"] as? String ?? "nil").")
}
}, failure: { _, error in
print("[Loki] Couldn't acknowledge delivery for message with hash: \(hash) due to error: \(error).")
})
}
} }

Loading…
Cancel
Save