Rotate profile key if blocklist intersects profile whitelist.
This commit is contained in:
parent
d8a0baf9ee
commit
c907721a18
|
@ -1627,7 +1627,6 @@
|
||||||
4598198D204E2F28009414F2 /* OWS108CallLoggingPreference.m */,
|
4598198D204E2F28009414F2 /* OWS108CallLoggingPreference.m */,
|
||||||
34D5872E208E2C4100D2255A /* OWS109OutgoingMessageState.h */,
|
34D5872E208E2C4100D2255A /* OWS109OutgoingMessageState.h */,
|
||||||
34D5872D208E2C4100D2255A /* OWS109OutgoingMessageState.m */,
|
34D5872D208E2C4100D2255A /* OWS109OutgoingMessageState.m */,
|
||||||
4C858A552130CBEC001B45D3 /* OWS110SortIdMigration.swift */,
|
|
||||||
349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */,
|
349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */,
|
||||||
346129931FD1E30000532771 /* OWSDatabaseMigration.h */,
|
346129931FD1E30000532771 /* OWSDatabaseMigration.h */,
|
||||||
346129941FD1E30000532771 /* OWSDatabaseMigration.m */,
|
346129941FD1E30000532771 /* OWSDatabaseMigration.m */,
|
||||||
|
|
|
@ -239,9 +239,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
itemWithTitle:@"Request Bogus group info"
|
itemWithTitle:@"Request Bogus group info"
|
||||||
actionBlock:^{
|
actionBlock:^{
|
||||||
OWSLogInfo(@"Requesting bogus group info for thread: %@", thread);
|
OWSLogInfo(@"Requesting bogus group info for thread: %@", thread);
|
||||||
OWSSyncGroupsRequestMessage *syncGroupsRequestMessage =
|
OWSSyncGroupsRequestMessage *syncGroupsRequestMessage = [[OWSSyncGroupsRequestMessage alloc]
|
||||||
[[OWSSyncGroupsRequestMessage alloc] initWithThread:thread
|
initWithThread:thread
|
||||||
groupId:[Randomness generateRandomBytes:16]];
|
groupId:[Randomness generateRandomBytes:kGroupIdLength]];
|
||||||
[SSKEnvironment.shared.messageSender enqueueMessage:syncGroupsRequestMessage
|
[SSKEnvironment.shared.messageSender enqueueMessage:syncGroupsRequestMessage
|
||||||
success:^{
|
success:^{
|
||||||
OWSLogWarn(@"Successfully sent Request Group Info message.");
|
OWSLogWarn(@"Successfully sent Request Group Info message.");
|
||||||
|
@ -3816,7 +3816,7 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
|
||||||
recipientId,
|
recipientId,
|
||||||
[TSAccountManager localNumber],
|
[TSAccountManager localNumber],
|
||||||
] mutableCopy];
|
] mutableCopy];
|
||||||
NSData *groupId = [Randomness generateRandomBytes:16];
|
NSData *groupId = [Randomness generateRandomBytes:kGroupIdLength];
|
||||||
TSGroupModel *groupModel =
|
TSGroupModel *groupModel =
|
||||||
[[TSGroupModel alloc] initWithTitle:groupName memberIds:recipientIds image:nil groupId:groupId];
|
[[TSGroupModel alloc] initWithTitle:groupName memberIds:recipientIds image:nil groupId:groupId];
|
||||||
|
|
||||||
|
@ -4309,7 +4309,7 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
|
||||||
recipientId,
|
recipientId,
|
||||||
[TSAccountManager localNumber],
|
[TSAccountManager localNumber],
|
||||||
] mutableCopy];
|
] mutableCopy];
|
||||||
NSData *groupId = [Randomness generateRandomBytes:16];
|
NSData *groupId = [Randomness generateRandomBytes:kGroupIdLength];
|
||||||
TSGroupModel *groupModel =
|
TSGroupModel *groupModel =
|
||||||
[[TSGroupModel alloc] initWithTitle:groupName memberIds:recipientIds image:nil groupId:groupId];
|
[[TSGroupModel alloc] initWithTitle:groupName memberIds:recipientIds image:nil groupId:groupId];
|
||||||
|
|
||||||
|
@ -4348,7 +4348,7 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
|
||||||
recipientId,
|
recipientId,
|
||||||
[TSAccountManager localNumber],
|
[TSAccountManager localNumber],
|
||||||
] mutableCopy];
|
] mutableCopy];
|
||||||
NSData *groupId = [Randomness generateRandomBytes:16];
|
NSData *groupId = [Randomness generateRandomBytes:kGroupIdLength];
|
||||||
TSGroupModel *groupModel =
|
TSGroupModel *groupModel =
|
||||||
[[TSGroupModel alloc] initWithTitle:groupName memberIds:recipientIds image:nil groupId:groupId];
|
[[TSGroupModel alloc] initWithTitle:groupName memberIds:recipientIds image:nil groupId:groupId];
|
||||||
|
|
||||||
|
|
|
@ -506,7 +506,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
[[TSGroupModel alloc] initWithTitle:[groupThread.groupModel.groupName stringByAppendingString:@" Copy"]
|
[[TSGroupModel alloc] initWithTitle:[groupThread.groupModel.groupName stringByAppendingString:@" Copy"]
|
||||||
memberIds:groupThread.groupModel.groupMemberIds
|
memberIds:groupThread.groupModel.groupMemberIds
|
||||||
image:groupThread.groupModel.groupImage
|
image:groupThread.groupModel.groupImage
|
||||||
groupId:[Randomness generateRandomBytes:16]];
|
groupId:[Randomness generateRandomBytes:kGroupIdLength]];
|
||||||
thread = [TSGroupThread getOrCreateThreadWithGroupModel:groupModel transaction:transaction];
|
thread = [TSGroupThread getOrCreateThreadWithGroupModel:groupModel transaction:transaction];
|
||||||
}];
|
}];
|
||||||
OWSAssertDebug(thread);
|
OWSAssertDebug(thread);
|
||||||
|
|
|
@ -86,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
- (void)commonInit
|
- (void)commonInit
|
||||||
{
|
{
|
||||||
_groupId = [Randomness generateRandomBytes:16];
|
_groupId = [Randomness generateRandomBytes:kGroupIdLength];
|
||||||
|
|
||||||
_messageSender = SSKEnvironment.shared.messageSender;
|
_messageSender = SSKEnvironment.shared.messageSender;
|
||||||
_contactsViewHelper = [[ContactsViewHelper alloc] initWithDelegate:self];
|
_contactsViewHelper = [[ContactsViewHelper alloc] initWithDelegate:self];
|
||||||
|
|
|
@ -80,11 +80,11 @@ class ConversationSearcherTest: SignalBaseTest {
|
||||||
SSKEnvironment.shared.contactsManager = ConversationSearcherContactsManager()
|
SSKEnvironment.shared.contactsManager = ConversationSearcherContactsManager()
|
||||||
|
|
||||||
self.dbConnection.readWrite { transaction in
|
self.dbConnection.readWrite { transaction in
|
||||||
let bookModel = TSGroupModel(title: "Book Club", memberIds: [aliceRecipientId, bobRecipientId], image: nil, groupId: Randomness.generateRandomBytes(16))
|
let bookModel = TSGroupModel(title: "Book Club", memberIds: [aliceRecipientId, bobRecipientId], image: nil, groupId: Randomness.generateRandomBytes(kGroupIdLength))
|
||||||
let bookClubGroupThread = TSGroupThread.getOrCreateThread(with: bookModel, transaction: transaction)
|
let bookClubGroupThread = TSGroupThread.getOrCreateThread(with: bookModel, transaction: transaction)
|
||||||
self.bookClubThread = ThreadViewModel(thread: bookClubGroupThread, transaction: transaction)
|
self.bookClubThread = ThreadViewModel(thread: bookClubGroupThread, transaction: transaction)
|
||||||
|
|
||||||
let snackModel = TSGroupModel(title: "Snack Club", memberIds: [aliceRecipientId], image: nil, groupId: Randomness.generateRandomBytes(16))
|
let snackModel = TSGroupModel(title: "Snack Club", memberIds: [aliceRecipientId], image: nil, groupId: Randomness.generateRandomBytes(kGroupIdLength))
|
||||||
let snackClubGroupThread = TSGroupThread.getOrCreateThread(with: snackModel, transaction: transaction)
|
let snackClubGroupThread = TSGroupThread.getOrCreateThread(with: snackModel, transaction: transaction)
|
||||||
self.snackClubThread = ThreadViewModel(thread: snackClubGroupThread, transaction: transaction)
|
self.snackClubThread = ThreadViewModel(thread: snackClubGroupThread, transaction: transaction)
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
OWSContactsManager *contactsManager = [[OWSContactsManager alloc] initWithPrimaryStorage:primaryStorage];
|
OWSContactsManager *contactsManager = [[OWSContactsManager alloc] initWithPrimaryStorage:primaryStorage];
|
||||||
ContactsUpdater *contactsUpdater = [ContactsUpdater new];
|
ContactsUpdater *contactsUpdater = [ContactsUpdater new];
|
||||||
OWSMessageSender *messageSender = [[OWSMessageSender alloc] initWithPrimaryStorage:primaryStorage];
|
OWSMessageSender *messageSender = [[OWSMessageSender alloc] initWithPrimaryStorage:primaryStorage];
|
||||||
|
OWSProfileManager *profileManager = [[OWSProfileManager alloc] initWithPrimaryStorage:primaryStorage];
|
||||||
OWSProfileManager *profileManager = [[OWSProfileManager alloc] initWithPrimaryStorage:primaryStorage
|
|
||||||
messageSender:messageSender
|
|
||||||
networkManager:networkManager];
|
|
||||||
|
|
||||||
OWSMessageManager *messageManager = [[OWSMessageManager alloc] initWithPrimaryStorage:primaryStorage];
|
OWSMessageManager *messageManager = [[OWSMessageManager alloc] initWithPrimaryStorage:primaryStorage];
|
||||||
OWSBlockingManager *blockingManager = [[OWSBlockingManager alloc] initWithPrimaryStorage:primaryStorage];
|
OWSBlockingManager *blockingManager = [[OWSBlockingManager alloc] initWithPrimaryStorage:primaryStorage];
|
||||||
OWSIdentityManager *identityManager = [[OWSIdentityManager alloc] initWithPrimaryStorage:primaryStorage];
|
OWSIdentityManager *identityManager = [[OWSIdentityManager alloc] initWithPrimaryStorage:primaryStorage];
|
||||||
|
|
|
@ -8,12 +8,6 @@ import SignalServiceKit
|
||||||
@objc
|
@objc
|
||||||
public class OWS111UDAttributesMigration: OWSDatabaseMigration {
|
public class OWS111UDAttributesMigration: OWSDatabaseMigration {
|
||||||
|
|
||||||
// MARK: - Singletons
|
|
||||||
|
|
||||||
private var networkManager: TSNetworkManager {
|
|
||||||
return SSKEnvironment.shared.networkManager
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: -
|
// MARK: -
|
||||||
|
|
||||||
// increment a similar constant for each migration.
|
// increment a similar constant for each migration.
|
||||||
|
|
|
@ -22,9 +22,7 @@ extern const NSUInteger kOWSProfileManager_MaxAvatarDiameter;
|
||||||
|
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
|
||||||
- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
|
- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage;
|
||||||
messageSender:(OWSMessageSender *)messageSender
|
|
||||||
networkManager:(TSNetworkManager *)networkManager;
|
|
||||||
|
|
||||||
+ (instancetype)sharedManager;
|
+ (instancetype)sharedManager;
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,11 @@
|
||||||
#import <SignalCoreKit/NSString+SSK.h>
|
#import <SignalCoreKit/NSString+SSK.h>
|
||||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||||
#import <SignalServiceKit/AppContext.h>
|
#import <SignalServiceKit/AppContext.h>
|
||||||
|
#import <SignalServiceKit/AppReadiness.h>
|
||||||
#import <SignalServiceKit/MIMETypeUtil.h>
|
#import <SignalServiceKit/MIMETypeUtil.h>
|
||||||
#import <SignalServiceKit/NSData+Image.h>
|
#import <SignalServiceKit/NSData+Image.h>
|
||||||
#import <SignalServiceKit/NSNotificationCenter+OWS.h>
|
#import <SignalServiceKit/NSNotificationCenter+OWS.h>
|
||||||
|
#import <SignalServiceKit/OWSBlockingManager.h>
|
||||||
#import <SignalServiceKit/OWSFileSystem.h>
|
#import <SignalServiceKit/OWSFileSystem.h>
|
||||||
#import <SignalServiceKit/OWSMessageSender.h>
|
#import <SignalServiceKit/OWSMessageSender.h>
|
||||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||||
|
@ -27,6 +29,7 @@
|
||||||
#import <SignalServiceKit/TSThread.h>
|
#import <SignalServiceKit/TSThread.h>
|
||||||
#import <SignalServiceKit/TSYapDatabaseObject.h>
|
#import <SignalServiceKit/TSYapDatabaseObject.h>
|
||||||
#import <SignalServiceKit/UIImage+OWS.h>
|
#import <SignalServiceKit/UIImage+OWS.h>
|
||||||
|
#import <SignalServiceKit/YapDatabaseConnection+OWS.h>
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@ -42,10 +45,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
|
|
||||||
@interface OWSProfileManager ()
|
@interface OWSProfileManager ()
|
||||||
|
|
||||||
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
|
||||||
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
||||||
@property (nonatomic, readonly) TSNetworkManager *networkManager;
|
|
||||||
@property (nonatomic, readonly) OWSIdentityManager *identityManager;
|
|
||||||
|
|
||||||
// This property can be accessed on any thread, while synchronized on self.
|
// This property can be accessed on any thread, while synchronized on self.
|
||||||
@property (atomic, readonly) OWSUserProfile *localUserProfile;
|
@property (atomic, readonly) OWSUserProfile *localUserProfile;
|
||||||
|
@ -72,8 +72,6 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
|
- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
|
||||||
messageSender:(OWSMessageSender *)messageSender
|
|
||||||
networkManager:(TSNetworkManager *)networkManager
|
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
|
@ -83,18 +81,18 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
|
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(primaryStorage);
|
OWSAssertDebug(primaryStorage);
|
||||||
OWSAssertDebug(messageSender);
|
|
||||||
OWSAssertDebug(messageSender);
|
|
||||||
|
|
||||||
_messageSender = messageSender;
|
|
||||||
_dbConnection = primaryStorage.newDatabaseConnection;
|
_dbConnection = primaryStorage.newDatabaseConnection;
|
||||||
_networkManager = networkManager;
|
|
||||||
|
|
||||||
_profileAvatarImageCache = [NSCache new];
|
_profileAvatarImageCache = [NSCache new];
|
||||||
_currentAvatarDownloads = [NSMutableSet new];
|
_currentAvatarDownloads = [NSMutableSet new];
|
||||||
|
|
||||||
OWSSingletonAssert();
|
OWSSingletonAssert();
|
||||||
|
|
||||||
|
[AppReadiness runNowOrWhenAppIsReady:^{
|
||||||
|
[self rotateLocalProfileKeyIfNecessarySync];
|
||||||
|
}];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +107,10 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
selector:@selector(applicationDidBecomeActive:)
|
selector:@selector(applicationDidBecomeActive:)
|
||||||
name:OWSApplicationDidBecomeActiveNotification
|
name:OWSApplicationDidBecomeActiveNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(blockListDidChange:)
|
||||||
|
name:kNSNotificationName_BlockListDidChange
|
||||||
|
object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Dependencies
|
#pragma mark - Dependencies
|
||||||
|
@ -124,7 +126,21 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
|
|
||||||
- (OWSIdentityManager *)identityManager
|
- (OWSIdentityManager *)identityManager
|
||||||
{
|
{
|
||||||
return [OWSIdentityManager sharedManager];
|
return SSKEnvironment.shared.identityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OWSMessageSender *)messageSender {
|
||||||
|
OWSAssertDebug(SSKEnvironment.shared.messageSender);
|
||||||
|
|
||||||
|
return SSKEnvironment.shared.messageSender;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (TSNetworkManager *)networkManager {
|
||||||
|
return SSKEnvironment.shared.networkManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OWSBlockingManager *)blockingManager {
|
||||||
|
return SSKEnvironment.shared.blockingManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - User Profile Accessor
|
#pragma mark - User Profile Accessor
|
||||||
|
@ -504,6 +520,154 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
[ProfileFetcherJob runWithRecipientId:localNumber ignoreThrottling:YES];
|
[ProfileFetcherJob runWithRecipientId:localNumber ignoreThrottling:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Profile Key Rotation
|
||||||
|
|
||||||
|
- (nullable NSString *)groupKeyForGroupId:(NSData *)groupId {
|
||||||
|
NSString *groupIdKey = [groupId hexadecimalString];
|
||||||
|
return groupIdKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (nullable NSData *)groupIdForGroupKey:(NSString *)groupKey {
|
||||||
|
NSMutableData *groupId = [NSMutableData new];
|
||||||
|
|
||||||
|
for (NSUInteger i = 0; i + 2 <= groupKey.length; i += 2) {
|
||||||
|
NSString *_Nullable byteString = [groupKey substringWithRange:NSMakeRange(i, 2)];
|
||||||
|
if (!byteString) {
|
||||||
|
OWSFailDebug(@"Couldn't slice group key.");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
unsigned byteValue;
|
||||||
|
if (![[NSScanner scannerWithString:byteString] scanHexInt:&byteValue]) {
|
||||||
|
OWSFailDebug(@"Couldn't parse hex byte: %@.", byteString);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if (byteValue > 0xff) {
|
||||||
|
OWSFailDebug(@"Invalid hex byte: %@ (%d).", byteString, byteValue);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
uint8_t byte = (uint8_t)(0xff & byteValue);
|
||||||
|
[groupId appendBytes:&byte length:1];
|
||||||
|
}
|
||||||
|
if (groupId.length != kGroupIdLength) {
|
||||||
|
OWSFailDebug(@"Parsed group id has unexpected length: %@ (%lu)",
|
||||||
|
groupId.hexadecimalString,
|
||||||
|
(unsigned long)groupId.length);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return [groupId copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rotateLocalProfileKeyIfNecessarySync {
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
|
[self rotateLocalProfileKeyIfNecessarySync];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rotateLocalProfileKeyIfNecessaryAsync {
|
||||||
|
OWSAssertDebug(AppReadiness.isAppReady);
|
||||||
|
|
||||||
|
NSMutableSet<NSString *> *whitelistedRecipientIds = [NSMutableSet new];
|
||||||
|
NSMutableSet<NSData *> *whitelistedGroupIds = [NSMutableSet new];
|
||||||
|
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||||
|
[whitelistedRecipientIds
|
||||||
|
addObjectsFromArray:[transaction allKeysInCollection:kOWSProfileManager_UserWhitelistCollection]];
|
||||||
|
|
||||||
|
NSArray<NSString *> *whitelistedGroupKeys =
|
||||||
|
[transaction allKeysInCollection:kOWSProfileManager_GroupWhitelistCollection];
|
||||||
|
for (NSString *groupKey in whitelistedGroupKeys) {
|
||||||
|
NSData *_Nullable groupId = [self groupIdForGroupKey:groupKey];
|
||||||
|
if (!groupId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[whitelistedGroupIds addObject:groupId];
|
||||||
|
|
||||||
|
TSGroupThread *_Nullable thread = [TSGroupThread threadWithGroupId:groupId transaction:transaction];
|
||||||
|
if (!thread) {
|
||||||
|
OWSLogInfo(@"Could not find whitelisted thread: %@", groupId.hexadecimalString);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[whitelistedRecipientIds addObjectsFromArray:thread.recipientIdentifiers];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
[whitelistedRecipientIds removeObject:[TSAccountManager localNumber]];
|
||||||
|
|
||||||
|
NSSet<NSString *> *blockedRecipientIds = [NSSet setWithArray:self.blockingManager.blockedPhoneNumbers];
|
||||||
|
NSSet<NSData *> *blockedGroupIds = [NSSet setWithArray:self.blockingManager.blockedGroupIds];
|
||||||
|
|
||||||
|
// Find the users and groups which are both a) blocked b) may have our current profile key.
|
||||||
|
NSMutableSet<NSString *> *intersectingRecipientIds = [blockedRecipientIds mutableCopy];
|
||||||
|
[intersectingRecipientIds intersectSet:whitelistedRecipientIds];
|
||||||
|
NSMutableSet<NSData *> *intersectingGroupIds = [blockedGroupIds mutableCopy];
|
||||||
|
[intersectingGroupIds intersectSet:whitelistedGroupIds];
|
||||||
|
|
||||||
|
BOOL isProfileKeySharedWithBlocked = (intersectingRecipientIds.count > 0 || intersectingGroupIds.count > 0);
|
||||||
|
if (!isProfileKeySharedWithBlocked) {
|
||||||
|
// No need to rotate the profile key.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate the profile key
|
||||||
|
|
||||||
|
// Make copies of the current local profile state.
|
||||||
|
OWSUserProfile *localUserProfile = self.localUserProfile;
|
||||||
|
NSString *_Nullable oldProfileName = localUserProfile.profileName;
|
||||||
|
NSString *_Nullable oldAvatarFileName = localUserProfile.avatarFileName;
|
||||||
|
NSData *_Nullable oldAvatarData = [self profileAvatarDataForRecipientId:self.tsAccountManager.localNumber];
|
||||||
|
|
||||||
|
// Rotate the stored profile key.
|
||||||
|
//
|
||||||
|
// This will always succeed.
|
||||||
|
[self.localUserProfile
|
||||||
|
updateWithProfileKey:[OWSAES256Key generateRandomKey]
|
||||||
|
dbConnection:self.dbConnection
|
||||||
|
completion:^{
|
||||||
|
// Remove blocked users and groups from profile whitelist.
|
||||||
|
//
|
||||||
|
// This will always succeed.
|
||||||
|
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||||
|
[transaction removeObjectsForKeys:intersectingRecipientIds.allObjects
|
||||||
|
inCollection:kOWSProfileManager_UserWhitelistCollection];
|
||||||
|
for (NSData *groupId in intersectingGroupIds) {
|
||||||
|
NSString *groupIdKey = [self groupKeyForGroupId:groupId];
|
||||||
|
[transaction removeObjectForKey:groupIdKey
|
||||||
|
inCollection:kOWSProfileManager_GroupWhitelistCollection];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
// Try to re-upload our profile name and avatar, if any.
|
||||||
|
//
|
||||||
|
// This may fail.
|
||||||
|
if (oldProfileName.length > 0) {
|
||||||
|
[self updateServiceWithProfileName:oldProfileName
|
||||||
|
success:^{
|
||||||
|
OWSLogInfo(@"Update to profile name after profile key rotation succeeded.");
|
||||||
|
}
|
||||||
|
failure:^{
|
||||||
|
OWSLogInfo(@"Update to profile name after profile key rotation failed.");
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldAvatarData.length > 0 && oldAvatarFileName.length > 0) {
|
||||||
|
[self uploadAvatarToService:oldAvatarData
|
||||||
|
success:^(NSString *_Nullable avatarUrlPath) {
|
||||||
|
OWSLogInfo(@"Update to profile avatar after profile key rotation succeeded.");
|
||||||
|
// We need to update the local profile with the avatar state since
|
||||||
|
// it is cleared during the "avatar update" process.
|
||||||
|
[self.localUserProfile updateWithAvatarUrlPath:avatarUrlPath
|
||||||
|
avatarFileName:oldAvatarFileName
|
||||||
|
dbConnection:self.dbConnection
|
||||||
|
completion:nil];
|
||||||
|
}
|
||||||
|
failure:^{
|
||||||
|
OWSLogInfo(@"Update to profile avatar after profile key rotation failed.");
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Profile Whitelist
|
#pragma mark - Profile Whitelist
|
||||||
|
|
||||||
- (void)clearProfileWhitelist
|
- (void)clearProfileWhitelist
|
||||||
|
@ -581,6 +745,10 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
{
|
{
|
||||||
OWSAssertDebug(recipientId.length > 0);
|
OWSAssertDebug(recipientId.length > 0);
|
||||||
|
|
||||||
|
if ([self.blockingManager isRecipientIdBlocked:recipientId]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
__block BOOL result = NO;
|
__block BOOL result = NO;
|
||||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||||
NSNumber *_Nullable oldValue =
|
NSNumber *_Nullable oldValue =
|
||||||
|
@ -594,7 +762,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
{
|
{
|
||||||
OWSAssertDebug(groupId.length > 0);
|
OWSAssertDebug(groupId.length > 0);
|
||||||
|
|
||||||
NSString *groupIdKey = [groupId hexadecimalString];
|
NSString *groupIdKey = [self groupKeyForGroupId:groupId];
|
||||||
|
|
||||||
__block BOOL didChange = NO;
|
__block BOOL didChange = NO;
|
||||||
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||||
|
@ -645,7 +813,11 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
{
|
{
|
||||||
OWSAssertDebug(groupId.length > 0);
|
OWSAssertDebug(groupId.length > 0);
|
||||||
|
|
||||||
NSString *groupIdKey = [groupId hexadecimalString];
|
if ([self.blockingManager isGroupIdBlocked:groupId]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *groupIdKey = [self groupKeyForGroupId:groupId];
|
||||||
|
|
||||||
__block BOOL result = NO;
|
__block BOOL result = NO;
|
||||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||||
|
@ -1173,6 +1345,14 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
||||||
// TODO: Sync if necessary.
|
// TODO: Sync if necessary.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)blockListDidChange:(NSNotification *)notification {
|
||||||
|
OWSAssertIsOnMainThread();
|
||||||
|
|
||||||
|
[AppReadiness runNowOrWhenAppIsReady:^{
|
||||||
|
[self rotateLocalProfileKeyIfNecessarySync];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -61,6 +61,10 @@ extern NSString *const kLocalProfileUniqueId;
|
||||||
dbConnection:(YapDatabaseConnection *)dbConnection
|
dbConnection:(YapDatabaseConnection *)dbConnection
|
||||||
completion:(nullable OWSUserProfileCompletion)completion;
|
completion:(nullable OWSUserProfileCompletion)completion;
|
||||||
|
|
||||||
|
- (void)updateWithProfileKey:(OWSAES256Key *)profileKey
|
||||||
|
dbConnection:(YapDatabaseConnection *)dbConnection
|
||||||
|
completion:(nullable OWSUserProfileCompletion)completion;
|
||||||
|
|
||||||
- (void)clearWithProfileKey:(OWSAES256Key *)profileKey
|
- (void)clearWithProfileKey:(OWSAES256Key *)profileKey
|
||||||
dbConnection:(YapDatabaseConnection *)dbConnection
|
dbConnection:(YapDatabaseConnection *)dbConnection
|
||||||
completion:(nullable OWSUserProfileCompletion)completion;
|
completion:(nullable OWSUserProfileCompletion)completion;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
extern const NSUInteger kGroupIdLength;
|
||||||
|
|
||||||
@interface TSGroupModel : TSYapDatabaseObject
|
@interface TSGroupModel : TSYapDatabaseObject
|
||||||
|
|
||||||
@property (nonatomic) NSArray<NSString *> *groupMemberIds;
|
@property (nonatomic) NSArray<NSString *> *groupMemberIds;
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
const NSUInteger kGroupIdLength = 16;
|
||||||
|
|
||||||
@interface TSGroupModel ()
|
@interface TSGroupModel ()
|
||||||
|
|
||||||
@property (nullable, nonatomic) NSString *groupName;
|
@property (nullable, nonatomic) NSString *groupName;
|
||||||
|
|
Loading…
Reference in New Issue