Rework profile fetch to reflect UD changes.

pull/1/head
Matthew Chen 6 years ago
parent 2eeba2d79f
commit 0b41e5e240

@ -1123,7 +1123,7 @@ typedef enum : NSUInteger {
{
[super viewDidAppear:animated];
[ProfileFetcherJob runWithThread:self.thread networkManager:self.networkManager];
[ProfileFetcherJob runWithThread:self.thread];
[self markVisibleMessagesAsRead];
[self startReadTimer];
[self updateNavigationBarSubtitleLabel];

@ -88,9 +88,7 @@ public class OWS106EnsureProfileComplete: OWSDatabaseMigration {
let (promise, fulfill, reject) = Promise<Void>.pending()
let networkManager = SSKEnvironment.shared.networkManager
ProfileFetcherJob(networkManager: networkManager).getProfile(recipientId: localRecipientId).then { _ -> Void in
ProfileFetcherJob().getProfile(recipientId: localRecipientId).then { _ -> Void in
Logger.info("verified recipient profile is in good shape: \(localRecipientId)")
fulfill(())

@ -495,7 +495,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
if (!localNumber) {
return;
}
[ProfileFetcherJob runWithRecipientId:localNumber networkManager:self.networkManager ignoreThrottling:YES];
[ProfileFetcherJob runWithRecipientId:localNumber ignoreThrottling:YES];
}
#pragma mark - Profile Whitelist
@ -716,7 +716,6 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
completion:^{
dispatch_async(dispatch_get_main_queue(), ^(void) {
[ProfileFetcherJob runWithRecipientId:recipientId
networkManager:self.networkManager
ignoreThrottling:YES];
});
}];

@ -9,10 +9,6 @@ import SignalServiceKit
@objc
public class ProfileFetcherJob: NSObject {
let networkManager: TSNetworkManager
let socketManager: TSSocketManager
let primaryStorage: OWSPrimaryStorage
// This property is only accessed on the main queue.
static var fetchDateMap = [String: Date]()
@ -21,22 +17,39 @@ public class ProfileFetcherJob: NSObject {
var backgroundTask: OWSBackgroundTask?
@objc
public class func run(thread: TSThread, networkManager: TSNetworkManager) {
ProfileFetcherJob(networkManager: networkManager).run(recipientIds: thread.recipientIdentifiers)
public class func run(thread: TSThread) {
ProfileFetcherJob().run(recipientIds: thread.recipientIdentifiers)
}
@objc
public class func run(recipientId: String, networkManager: TSNetworkManager, ignoreThrottling: Bool) {
ProfileFetcherJob(networkManager: networkManager, ignoreThrottling: ignoreThrottling).run(recipientIds: [recipientId])
public class func run(recipientId: String, ignoreThrottling: Bool) {
ProfileFetcherJob(ignoreThrottling: ignoreThrottling).run(recipientIds: [recipientId])
}
public init(networkManager: TSNetworkManager, ignoreThrottling: Bool = false) {
self.networkManager = networkManager
self.socketManager = TSSocketManager.shared()
self.primaryStorage = OWSPrimaryStorage.shared()
public init(ignoreThrottling: Bool = false) {
self.ignoreThrottling = ignoreThrottling
}
// MARK: - Dependencies
private var networkManager: TSNetworkManager {
return SSKEnvironment.shared.networkManager
}
private var socketManager: TSSocketManager {
return TSSocketManager.shared()
}
private var primaryStorage: OWSPrimaryStorage {
return SSKEnvironment.shared.primaryStorage
}
private var udManager: OWSUDManager {
return SSKEnvironment.shared.udManager
}
// MARK: -
public func run(recipientIds: [String]) {
AssertIsOnMainThread()
@ -117,7 +130,7 @@ public class ProfileFetcherJob: NSObject {
self.socketManager.make(request,
success: { (responseObject: Any?) -> Void in
do {
let profile = try SignalServiceProfile(recipientId: recipientId, rawResponse: responseObject)
let profile = try SignalServiceProfile(recipientId: recipientId, responseObject: responseObject)
fulfill(profile)
} catch {
reject(error)
@ -130,7 +143,7 @@ public class ProfileFetcherJob: NSObject {
self.networkManager.makeRequest(request,
success: { (_: URLSessionDataTask?, responseObject: Any?) -> Void in
do {
let profile = try SignalServiceProfile(recipientId: recipientId, rawResponse: responseObject)
let profile = try SignalServiceProfile(recipientId: recipientId, responseObject: responseObject)
fulfill(profile)
} catch {
reject(error)
@ -155,6 +168,13 @@ public class ProfileFetcherJob: NSObject {
OWSProfileManager.shared().updateProfile(forRecipientId: signalServiceProfile.recipientId,
profileNameEncrypted: signalServiceProfile.profileNameEncrypted,
avatarUrlPath: signalServiceProfile.avatarUrlPath)
udManager.setShouldAllowUnrestrictedAccess(recipientId: signalServiceProfile.recipientId, shouldAllowUnrestrictedAccess: signalServiceProfile.hasUnrestrictedUnidentifiedAccess)
if signalServiceProfile.unidentifiedAccessKey != nil {
udManager.addUDRecipientId(signalServiceProfile.recipientId)
} else {
udManager.removeUDRecipientId(signalServiceProfile.recipientId)
}
}
private func verifyIdentityUpToDateAsync(recipientId: String, latestIdentityKey: Data) {
@ -182,37 +202,33 @@ public class SignalServiceProfile: NSObject {
public let identityKey: Data
public let profileNameEncrypted: Data?
public let avatarUrlPath: String?
public let unidentifiedAccessKey: Data?
public let hasUnrestrictedUnidentifiedAccess: Bool
init(recipientId: String, rawResponse: Any?) throws {
init(recipientId: String, responseObject: Any?) throws {
self.recipientId = recipientId
guard let responseDict = rawResponse as? [String: Any?] else {
throw ValidationError.invalid(description: "unexpected type: \(String(describing: rawResponse))")
guard let params = ParamParser(responseObject: responseObject) else {
throw ValidationError.invalid(description: "invalid response: \(String(describing: responseObject))")
}
guard let identityKeyString = responseDict["identityKey"] as? String else {
throw ValidationError.invalidIdentityKey(description: "missing identity key: \(String(describing: rawResponse))")
}
guard let identityKeyWithType = Data(base64Encoded: identityKeyString) else {
throw ValidationError.invalidIdentityKey(description: "unable to parse identity key: \(identityKeyString)")
}
let identityKeyWithType = try params.requiredBase64EncodedData(key: "identityKey")
let kIdentityKeyLength = 33
guard identityKeyWithType.count == kIdentityKeyLength else {
throw ValidationError.invalidIdentityKey(description: "malformed key \(identityKeyString) with decoded length: \(identityKeyWithType.count)")
throw ValidationError.invalidIdentityKey(description: "malformed identity key \(identityKeyWithType.hexadecimalString) with decoded length: \(identityKeyWithType.count)")
}
// `removeKeyType` is an objc category method only on NSData, so temporarily cast.
self.identityKey = (identityKeyWithType as NSData).removeKeyType() as Data
if let profileNameString = responseDict["name"] as? String {
guard let data = Data(base64Encoded: profileNameString) else {
throw ValidationError.invalidProfileName(description: "unable to parse profile name: \(profileNameString)")
}
self.profileNameEncrypted = data
} else {
self.profileNameEncrypted = nil
}
self.profileNameEncrypted = try params.optionalBase64EncodedData(key: "name")
self.avatarUrlPath = responseDict["avatar"] as? String
let avatarUrlPath: String? = try params.optional(key: "avatar")
self.avatarUrlPath = avatarUrlPath
// `removeKeyType` is an objc category method only on NSData, so temporarily cast.
self.identityKey = (identityKeyWithType as NSData).removeKeyType() as Data
// TODO: Should this key be "unidentifiedAccessKey" or "unidentifiedAccess"?
// The docs don't agree with the response from staging.
self.unidentifiedAccessKey = try params.optionalBase64EncodedData(key: "unidentifiedAccess")
self.hasUnrestrictedUnidentifiedAccess = try params.optionalBool(key: "unrestrictedUnidentifiedAccess", defaultValue: false)
}
}

@ -524,6 +524,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[recipientIds addObjectsFromArray:message.sendingRecipientIds];
// Only send to members in the latest known group member list.
[recipientIds intersectSet:[NSSet setWithArray:gThread.groupModel.groupMemberIds]];
if ([recipientIds containsObject:TSAccountManager.localNumber]) {
OWSFailDebug(@"Message send recipients should not include self.");
}
} else if ([message isKindOfClass:[OWSOutgoingSyncMessage class]]) {
[recipientIds addObject:[TSAccountManager localNumber]];
} else if ([thread isKindOfClass:[TSContactThread class]]) {
@ -545,6 +549,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}
[recipientIds addObject:recipientContactId];
if ([recipientIds containsObject:TSAccountManager.localNumber]) {
OWSFailDebug(@"Message send recipients should not include self.");
}
} else {
// Neither a group nor contact thread? This should never happen.
OWSFailDebug(@"Unknown message type: %@", [message class]);
@ -552,15 +560,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError();
[error setIsRetryable:NO];
failureHandler(error);
return;
}
[recipientIds minusSet:[NSSet setWithArray:self.blockingManager.blockedPhoneNumbers]];
if ([recipientIds containsObject:TSAccountManager.localNumber]) {
OWSFailDebug(@"Message send recipients should not include self.");
}
[recipientIds removeObject:TSAccountManager.localNumber];
// Mark skipped recipients as such. We skip because:
//
// * Recipient is no longer in the group.

@ -39,9 +39,13 @@ public enum OWSUDError: Error {
// MARK: - Unrestricted Access
@objc func shouldAllowUnrestrictedAccess() -> Bool
@objc func shouldAllowUnrestrictedAccessLocal() -> Bool
@objc func setShouldAllowUnrestrictedAccess(_ value: Bool)
@objc func setShouldAllowUnrestrictedAccessLocal(_ value: Bool)
@objc func shouldAllowUnrestrictedAccess(recipientId: String) -> Bool
@objc func setShouldAllowUnrestrictedAccess(recipientId: String, shouldAllowUnrestrictedAccess: Bool)
}
// MARK: -
@ -51,10 +55,11 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
private let dbConnection: YapDatabaseConnection
private let kUDRecipientModeCollection = "kUDRecipientModeCollection"
private let kUDCollection = "kUDCollection"
private let kUDCurrentSenderCertificateKey = "kUDCurrentSenderCertificateKey"
private let kUDUnrestrictedAccessKey = "kUDUnrestrictedAccessKey"
private let kUDRecipientModeCollection = "kUDRecipientModeCollection"
private let kUDUnrestrictedAccessCollection = "kUDUnrestrictedAccessCollection"
@objc
public required init(primaryStorage: OWSPrimaryStorage) {
@ -215,12 +220,22 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
// MARK: - Unrestricted Access
@objc
public func shouldAllowUnrestrictedAccess() -> Bool {
return dbConnection.bool(forKey: kUDUnrestrictedAccessKey, inCollection: kUDRecipientModeCollection, defaultValue: false)
public func shouldAllowUnrestrictedAccessLocal() -> Bool {
return dbConnection.bool(forKey: kUDUnrestrictedAccessKey, inCollection: kUDCollection, defaultValue: false)
}
@objc
public func setShouldAllowUnrestrictedAccessLocal(_ value: Bool) {
dbConnection.setBool(value, forKey: kUDUnrestrictedAccessKey, inCollection: kUDCollection)
}
@objc
public func shouldAllowUnrestrictedAccess(recipientId: String) -> Bool {
return dbConnection.bool(forKey: recipientId, inCollection: kUDUnrestrictedAccessCollection, defaultValue: false)
}
@objc
public func setShouldAllowUnrestrictedAccess(_ value: Bool) {
dbConnection.setBool(value, forKey: kUDUnrestrictedAccessKey, inCollection: kUDRecipientModeCollection)
public func setShouldAllowUnrestrictedAccess(recipientId: String, shouldAllowUnrestrictedAccess: Bool) {
dbConnection.setBool(shouldAllowUnrestrictedAccess, forKey: recipientId, inCollection: kUDUnrestrictedAccessCollection)
}
}

@ -281,7 +281,7 @@ NS_ASSUME_NONNULL_BEGIN
// Crash app if UD cannot be enabled.
OWSFail(@"Could not determine UD access key: %@.", error);
}
BOOL allowUnrestrictedUD = [self.udManager shouldAllowUnrestrictedAccess] && udAccessKey != nil;
BOOL allowUnrestrictedUD = [self.udManager shouldAllowUnrestrictedAccessLocal] && udAccessKey != nil;
NSMutableDictionary *accountAttributes = [@{
@"signalingKey" : signalingKey,

@ -69,16 +69,31 @@ public class OWSFakeUDManager: NSObject, OWSUDManager {
// MARK: - Unrestricted Access
private var _shouldAllowUnrestrictedAccess = false
private var _shouldAllowUnrestrictedAccessLocal = false
private var _shouldAllowUnrestrictedAccessSet = Set<String>()
@objc
public func shouldAllowUnrestrictedAccess() -> Bool {
return _shouldAllowUnrestrictedAccess
public func shouldAllowUnrestrictedAccessLocal() -> Bool {
return _shouldAllowUnrestrictedAccessLocal
}
@objc
public func setShouldAllowUnrestrictedAccess(_ value: Bool) {
_shouldAllowUnrestrictedAccess = value
public func setShouldAllowUnrestrictedAccessLocal(_ value: Bool) {
_shouldAllowUnrestrictedAccessLocal = value
}
@objc
public func shouldAllowUnrestrictedAccess(recipientId: String) -> Bool {
return _shouldAllowUnrestrictedAccessSet.contains(recipientId)
}
@objc
public func setShouldAllowUnrestrictedAccess(recipientId: String, shouldAllowUnrestrictedAccess: Bool) {
if shouldAllowUnrestrictedAccess {
_shouldAllowUnrestrictedAccessSet.insert(recipientId)
} else {
_shouldAllowUnrestrictedAccessSet.remove(recipientId)
}
}
}

@ -139,4 +139,13 @@ public class ParamParser {
return data
}
// MARK: Bool
public func optionalBool(key: Key, defaultValue: Bool) throws -> Bool {
guard let optionalValue: Bool = try optional(key: key) else {
return defaultValue
}
return optionalValue
}
}

Loading…
Cancel
Save