From 1f6cbd399e9dbae3f7c80e5e044fcd3d7f0b904d Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 28 Feb 2018 09:58:54 -0500 Subject: [PATCH] Sketch out 2FA feature. --- .../NotificationSettingsViewController.m | 50 +++------ .../PrivacySettingsTableViewController.m | 37 +++++- .../ViewControllers/OWSTableViewController.h | 9 +- .../ViewControllers/OWSTableViewController.m | 33 ++++-- .../Requests/OWSDeviceProvisioningRequest.m | 9 +- .../Network/API/Requests/OWSRequestFactory.h | 19 ++++ .../Network/API/Requests/OWSRequestFactory.m | 31 ++++++ .../Requests/TSContactsIntersectionRequest.m | 17 +-- .../API/Requests/TSRecipientPrekeyRequest.m | 20 ++-- .../API/Requests/TSRegisterForPushRequest.m | 19 ++-- .../API/Requests/TSRegisterPrekeysRequest.m | 11 +- .../Requests/TSRegisterSignedPrekeyRequest.m | 9 +- .../src/Network/API/Requests/TSRequest.h | 8 +- .../src/Network/API/Requests/TSRequest.m | 19 +++- .../TSRequestVerificationCodeRequest.m | 6 +- .../API/Requests/TSSubmitMessageRequest.m | 23 ++-- .../API/Requests/TSUpdateAttributesRequest.m | 6 +- .../API/Requests/TSVerifyCodeRequest.m | 11 +- .../src/Network/API/TSNetworkManager.m | 5 +- SignalServiceKit/src/TSConstants.h | 23 ++-- SignalServiceKit/src/Util/OWS2FAManager.h | 25 +++++ SignalServiceKit/src/Util/OWS2FAManager.m | 105 ++++++++++++++++++ 22 files changed, 363 insertions(+), 132 deletions(-) create mode 100644 SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h create mode 100644 SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m create mode 100644 SignalServiceKit/src/Util/OWS2FAManager.h create mode 100644 SignalServiceKit/src/Util/OWS2FAManager.m diff --git a/Signal/src/ViewControllers/NotificationSettingsViewController.m b/Signal/src/ViewControllers/NotificationSettingsViewController.m index f299fce92..430c2ebb9 100644 --- a/Signal/src/ViewControllers/NotificationSettingsViewController.m +++ b/Signal/src/ViewControllers/NotificationSettingsViewController.m @@ -38,21 +38,15 @@ OWSTableSection *soundsSection = [OWSTableSection new]; soundsSection.headerTitle = NSLocalizedString(@"SETTINGS_SECTION_SOUNDS", @"Header Label for the sounds section of settings views."); - - [soundsSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ - UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 - reuseIdentifier:@"UITableViewCellStyleValue1"]; - cell.textLabel.text = NSLocalizedString(@"SETTINGS_ITEM_NOTIFICATION_SOUND", - @"Label for settings view that allows user to change the notification sound."); - OWSSound sound = [OWSSounds globalNotificationSound]; - cell.detailTextLabel.text = [OWSSounds displayNameForSound:sound]; - [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; - return cell; - } - actionBlock:^{ - OWSSoundSettingsViewController *vc = [OWSSoundSettingsViewController new]; - [weakSelf.navigationController pushViewController:vc animated:YES]; - }]]; + [soundsSection + addItem:[OWSTableItem disclosureItemWithText: + NSLocalizedString(@"SETTINGS_ITEM_NOTIFICATION_SOUND", + @"Label for settings view that allows user to change the notification sound.") + detailText:[OWSSounds displayNameForSound:[OWSSounds globalNotificationSound]] + actionBlock:^{ + OWSSoundSettingsViewController *vc = [OWSSoundSettingsViewController new]; + [weakSelf.navigationController pushViewController:vc animated:YES]; + }]]; NSString *inAppSoundsLabelText = NSLocalizedString(@"NOTIFICATIONS_SECTION_INAPP", @"Table cell switch label. When disabled, Signal will not play notification sounds while the app is in the " @@ -65,23 +59,15 @@ OWSTableSection *backgroundSection = [OWSTableSection new]; backgroundSection.headerTitle = NSLocalizedString(@"SETTINGS_NOTIFICATION_CONTENT_TITLE", @"table section header"); - [backgroundSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ - UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 - reuseIdentifier:@"UITableViewCellStyleValue1"]; - - NotificationType notifType = [prefs notificationPreviewType]; - NSString *detailString = [prefs nameForNotificationPreviewType:notifType]; - cell.textLabel.text = NSLocalizedString(@"NOTIFICATIONS_SHOW", nil); - cell.detailTextLabel.text = detailString; - [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; - - return cell; - } - actionBlock:^{ - NotificationSettingsOptionsViewController *vc = - [NotificationSettingsOptionsViewController new]; - [weakSelf.navigationController pushViewController:vc animated:YES]; - }]]; + [backgroundSection + addItem:[OWSTableItem + disclosureItemWithText:NSLocalizedString(@"NOTIFICATIONS_SHOW", nil) + detailText:[prefs nameForNotificationPreviewType:[prefs notificationPreviewType]] + actionBlock:^{ + NotificationSettingsOptionsViewController *vc = + [NotificationSettingsOptionsViewController new]; + [weakSelf.navigationController pushViewController:vc animated:YES]; + }]]; backgroundSection.footerTitle = NSLocalizedString(@"SETTINGS_NOTIFICATION_CONTENT_DESCRIPTION", @"table section footer"); [contents addSection:backgroundSection]; diff --git a/Signal/src/ViewControllers/PrivacySettingsTableViewController.m b/Signal/src/ViewControllers/PrivacySettingsTableViewController.m index f66ff9745..4bf43c4f9 100644 --- a/Signal/src/ViewControllers/PrivacySettingsTableViewController.m +++ b/Signal/src/ViewControllers/PrivacySettingsTableViewController.m @@ -7,6 +7,7 @@ #import "Signal-Swift.h" #import #import +#import #import NS_ASSUME_NONNULL_BEGIN @@ -120,7 +121,31 @@ NS_ASSUME_NONNULL_BEGIN }]]; [contents addSection:historyLogsSection]; - self.contents = contents; + OWSTableSection *twoFactorAuthSection = [OWSTableSection new]; + twoFactorAuthSection.headerTitle = NSLocalizedString( + @"SETTINGS_TWO_FACTOR_AUTH_TITLE", @"Title for the 'two factor auth' section of the privacy settings."); + BOOL is2FAEnabled = [OWS2FAManager.sharedManager is2FAEnabled]; + [twoFactorAuthSection + addItem:[OWSTableItem + disclosureItemWithText: + (is2FAEnabled ? NSLocalizedString(@"SETTINGS_TWO_FACTOR_AUTH_ENABLE", + @"Label for the 'enable two factor auth' item of the privacy settings.") + : NSLocalizedString(@"SETTINGS_TWO_FACTOR_AUTH_DISABLE", + @"Label for the 'disable two factor auth' item of the privacy settings.")) + actionBlock:^{ + if (is2FAEnabled) { + [weakSelf disable2FA]; + } else { + [weakSelf enable2FA]; + } + }]]; + [contents addSection:twoFactorAuthSection]; + + OWS2FAManager + .h + + self.contents + = contents; } #pragma mark - Events @@ -214,6 +239,16 @@ NS_ASSUME_NONNULL_BEGIN [SignalApp.sharedApp.callService createCallUIAdapter]; } +- (void)enable2FA +{ + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); +} + +- (void)disable2FA +{ + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); +} + #pragma mark - Log util + (NSString *)tag diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.h b/SignalMessaging/ViewControllers/OWSTableViewController.h index 12a390a90..e086cd2bd 100644 --- a/SignalMessaging/ViewControllers/OWSTableViewController.h +++ b/SignalMessaging/ViewControllers/OWSTableViewController.h @@ -44,11 +44,6 @@ extern const CGFloat kOWSTable_DefaultCellHeight; #pragma mark - -typedef NS_ENUM(NSInteger, OWSTableItemType) { - OWSTableItemTypeDefault, - OWSTableItemTypeAction, -}; - typedef void (^OWSTableActionBlock)(void); typedef void (^OWSTableSubPageBlock)(UIViewController *viewController); typedef UITableViewCell *_Nonnull (^OWSTableCustomCellBlock)(void); @@ -72,6 +67,10 @@ typedef UITableViewCell *_Nonnull (^OWSTableCustomCellBlock)(void); + (OWSTableItem *)disclosureItemWithText:(NSString *)text actionBlock:(nullable OWSTableActionBlock)actionBlock; ++ (OWSTableItem *)disclosureItemWithText:(NSString *)text + detailText:(NSString *)detailText + actionBlock:(nullable OWSTableActionBlock)actionBlock; + + (OWSTableItem *)disclosureItemWithText:(NSString *)text customRowHeight:(CGFloat)customRowHeight actionBlock:(nullable OWSTableActionBlock)actionBlock; diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.m b/SignalMessaging/ViewControllers/OWSTableViewController.m index 7f75932f9..f556d9284 100644 --- a/SignalMessaging/ViewControllers/OWSTableViewController.m +++ b/SignalMessaging/ViewControllers/OWSTableViewController.m @@ -83,7 +83,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; @interface OWSTableItem () -@property (nonatomic) OWSTableItemType itemType; @property (nonatomic, nullable) NSString *title; @property (nonatomic, nullable) OWSTableActionBlock actionBlock; @@ -102,7 +101,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(title.length > 0); OWSTableItem *item = [OWSTableItem new]; - item.itemType = OWSTableItemTypeAction; item.actionBlock = actionBlock; item.title = title; return item; @@ -116,7 +114,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(customRowHeight > 0); OWSTableItem *item = [OWSTableItem new]; - item.itemType = (actionBlock != nil ? OWSTableItemTypeAction : OWSTableItemTypeDefault); item.actionBlock = actionBlock; item.customCell = customCell; item.customRowHeight = @(customRowHeight); @@ -140,7 +137,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(customCellBlock); OWSTableItem *item = [OWSTableItem new]; - item.itemType = (actionBlock != nil ? OWSTableItemTypeAction : OWSTableItemTypeDefault); item.actionBlock = actionBlock; item.customCellBlock = customCellBlock; return item; @@ -164,7 +160,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(actionBlock); OWSTableItem *item = [OWSTableItem new]; - item.itemType = OWSTableItemTypeAction; item.actionBlock = actionBlock; item.customCellBlock = ^{ UITableViewCell *cell = [UITableViewCell new]; @@ -188,13 +183,34 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; return item; } ++ (OWSTableItem *)disclosureItemWithText:(NSString *)text + detailText:(NSString *)detailText + actionBlock:(nullable OWSTableActionBlock)actionBlock +{ + OWSAssert(text.length > 0); + OWSAssert(actionBlock); + + OWSTableItem *item = [OWSTableItem new]; + item.actionBlock = actionBlock; + item.customCellBlock = ^{ + UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 + reuseIdentifier:@"UITableViewCellStyleValue1"]; + cell.textLabel.text = text; + cell.textLabel.font = [UIFont ows_regularFontWithSize:18.f]; + cell.textLabel.textColor = [UIColor blackColor]; + cell.detailTextLabel.text = detailText; + [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; + return cell; + }; + return item; +} + + (OWSTableItem *)subPageItemWithText:(NSString *)text actionBlock:(nullable OWSTableSubPageBlock)actionBlock { OWSAssert(text.length > 0); OWSAssert(actionBlock); OWSTableItem *item = [OWSTableItem new]; - item.itemType = OWSTableItemTypeAction; __weak OWSTableItem *weakItem = item; item.actionBlock = ^{ OWSTableItem *strongItem = weakItem; @@ -233,7 +249,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(actionBlock); OWSTableItem *item = [OWSTableItem new]; - item.itemType = OWSTableItemTypeAction; item.actionBlock = actionBlock; item.customCellBlock = ^{ UITableViewCell *cell = [UITableViewCell new]; @@ -250,7 +265,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(text.length > 0); OWSTableItem *item = [OWSTableItem new]; - item.itemType = OWSTableItemTypeAction; item.customCellBlock = ^{ UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = text; @@ -282,7 +296,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(text.length > 0); OWSTableItem *item = [OWSTableItem new]; - item.itemType = OWSTableItemTypeAction; item.customCellBlock = ^{ UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = text; @@ -300,7 +313,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(accessoryText.length > 0); OWSTableItem *item = [OWSTableItem new]; - item.itemType = OWSTableItemTypeAction; item.customCellBlock = ^{ UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = text; @@ -337,7 +349,6 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; OWSAssert(selector); OWSTableItem *item = [OWSTableItem new]; - item.itemType = OWSTableItemTypeAction; __weak id weakTarget = target; item.customCellBlock = ^{ UITableViewCell *cell = [UITableViewCell new]; diff --git a/SignalServiceKit/src/Network/API/Requests/OWSDeviceProvisioningRequest.m b/SignalServiceKit/src/Network/API/Requests/OWSDeviceProvisioningRequest.m index 21f627183..915e511af 100644 --- a/SignalServiceKit/src/Network/API/Requests/OWSDeviceProvisioningRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/OWSDeviceProvisioningRequest.m @@ -1,4 +1,6 @@ -// Copyright (c) 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// #import "OWSDeviceProvisioningRequest.h" #import "TSConstants.h" @@ -17,7 +19,10 @@ NS_ASSUME_NONNULL_BEGIN } self.HTTPMethod = @"PUT"; - [self.parameters addEntriesFromDictionary:@{ @"body" : [messageBody base64EncodedString] }]; + + self.parameters = @{ + @"body" : [messageBody base64EncodedString], + }; return self; } diff --git a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h new file mode 100644 index 000000000..0322b184a --- /dev/null +++ b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +NS_ASSUME_NONNULL_BEGIN + +@class TSRequest; + +@interface OWSRequestFactory : NSObject + +- (instancetype)init NS_UNAVAILABLE; + ++ (TSRequest *)enable2FARequestWithPin:(NSString *)pin; + ++ (TSRequest *)disable2FARequest; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m new file mode 100644 index 000000000..f6ec848b4 --- /dev/null +++ b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m @@ -0,0 +1,31 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "OWSRequestFactory.h" +#import "TSConstants.h" +#import "TSRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation OWSRequestFactory + ++ (TSRequest *)enable2FARequestWithPin:(NSString *)pin; +{ + OWSAssert(pin.length > 0); + + return [TSRequest requestWithUrl:[NSURL URLWithString:textSecure2FAAPI] + method:@"PUT" + parameters:@{ + @"pin" : pin, + }]; +} + ++ (TSRequest *)disable2FARequest +{ + return [TSRequest requestWithUrl:[NSURL URLWithString:textSecure2FAAPI] method:@"DELETE" parameters:@{}]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Network/API/Requests/TSContactsIntersectionRequest.m b/SignalServiceKit/src/Network/API/Requests/TSContactsIntersectionRequest.m index 9d0ac456e..13c728238 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSContactsIntersectionRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSContactsIntersectionRequest.m @@ -1,14 +1,9 @@ // -// TSContactsIntersection.m -// TextSecureiOS +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -// Created by Frederic Jacobs on 10/12/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" #import "TSContactsIntersectionRequest.h" +#import "TSConstants.h" @implementation TSContactsIntersectionRequest @@ -16,9 +11,15 @@ self = [self initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", textSecureDirectoryAPI, @"tokens"]]]; + if (!self) { + return nil; + } + self.HTTPMethod = @"PUT"; - [self.parameters addEntriesFromDictionary:@{ @"contacts" : hashes }]; + self.parameters = @{ + @"contacts" : hashes, + }; return self; } diff --git a/SignalServiceKit/src/Network/API/Requests/TSRecipientPrekeyRequest.m b/SignalServiceKit/src/Network/API/Requests/TSRecipientPrekeyRequest.m index 0ac018429..813956e14 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSRecipientPrekeyRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSRecipientPrekeyRequest.m @@ -1,23 +1,21 @@ // -// TSGetRecipientPrekey.m -// TextSecureiOS -// -// Created by Christine Corbett Moran on 11/30/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import "TSConstants.h" #import "TSRecipientPrekeyRequest.h" +#import "TSConstants.h" @implementation TSRecipientPrekeyRequest - (TSRequest *)initWithRecipient:(NSString *)recipientNumber deviceId:(NSString *)deviceId { - NSString *recipientInformation = recipientNumber; + self = [super + initWithURL:[NSURL + URLWithString:[NSString + stringWithFormat:@"%@/%@/%@", textSecureKeysAPI, recipientNumber, deviceId]]]; - self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@/%@", - textSecureKeysAPI, - recipientInformation, - deviceId]]]; + if (!self) { + return nil; + } self.HTTPMethod = @"GET"; self.parameters = nil; diff --git a/SignalServiceKit/src/Network/API/Requests/TSRegisterForPushRequest.m b/SignalServiceKit/src/Network/API/Requests/TSRegisterForPushRequest.m index 4f390d4e9..a158f680b 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSRegisterForPushRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSRegisterForPushRequest.m @@ -1,14 +1,9 @@ // -// TSRegisterForPushRequest.m -// TextSecureiOS +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -// Created by Frederic Jacobs on 10/13/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" #import "TSRegisterForPushRequest.h" +#import "TSConstants.h" @implementation TSRegisterForPushRequest @@ -16,14 +11,20 @@ self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", textSecureAccountsAPI, @"apn"]]]; + if (!self) { + return nil; + } + self.HTTPMethod = @"PUT"; - self.parameters = [@{ @"apnRegistrationId" : identifier } mutableCopy]; + NSMutableDictionary *parameters = [@{ @"apnRegistrationId" : identifier } mutableCopy]; if (voipId) { - [self.parameters setObject:voipId forKeyedSubscript:@"voipRegistrationId"]; + parameters[@"voipRegistrationId"] = voipId; } + self.parameters = parameters; + return self; } diff --git a/SignalServiceKit/src/Network/API/Requests/TSRegisterPrekeysRequest.m b/SignalServiceKit/src/Network/API/Requests/TSRegisterPrekeysRequest.m index 8bf641b72..fec0bb937 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSRegisterPrekeysRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSRegisterPrekeysRequest.m @@ -1,14 +1,13 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import "TSConstants.h" #import "TSRegisterPrekeysRequest.h" - -#import +#import "TSConstants.h" #import #import #import +#import @implementation TSRegisterPrekeysRequest @@ -17,6 +16,10 @@ signedPreKeyRecord:(SignedPreKeyRecord *)signedRecord preKeyLastResort:(PreKeyRecord *)lastResort { self = [super initWithURL:[NSURL URLWithString:textSecureKeysAPI]]; + if (!self) { + return nil; + } + self.HTTPMethod = @"PUT"; NSString *publicIdentityKey = [[identityKeyPublic prependKeyType] base64EncodedStringWithOptions:0]; diff --git a/SignalServiceKit/src/Network/API/Requests/TSRegisterSignedPrekeyRequest.m b/SignalServiceKit/src/Network/API/Requests/TSRegisterSignedPrekeyRequest.m index 290aa8716..caa41437a 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSRegisterSignedPrekeyRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSRegisterSignedPrekeyRequest.m @@ -1,20 +1,23 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "TSRegisterSignedPrekeyRequest.h" #import "TSConstants.h" - -#import #import #import #import +#import @implementation TSRegisterSignedPrekeyRequest - (id)initWithSignedPreKeyRecord:(SignedPreKeyRecord *)signedRecord { self = [super initWithURL:[NSURL URLWithString:textSecureSignedKeysAPI]]; + if (!self) { + return nil; + } + self.HTTPMethod = @"PUT"; NSDictionary *serializedKeyRegistrationParameters = [self dictionaryFromSignedPreKey:signedRecord]; diff --git a/SignalServiceKit/src/Network/API/Requests/TSRequest.h b/SignalServiceKit/src/Network/API/Requests/TSRequest.h index 651ebe9e5..25a8eec27 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSRequest.h +++ b/SignalServiceKit/src/Network/API/Requests/TSRequest.h @@ -1,11 +1,13 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // @interface TSRequest : NSMutableURLRequest -@property (nonatomic, retain) NSMutableDictionary *parameters; +@property (nonatomic) NSDictionary *parameters; -- (void)makeAuthenticatedRequest; ++ (instancetype)requestWithUrl:(NSURL *)url + method:(NSString *)method + parameters:(NSDictionary *)parameters; @end diff --git a/SignalServiceKit/src/Network/API/Requests/TSRequest.m b/SignalServiceKit/src/Network/API/Requests/TSRequest.m index 5606c1a3b..db653bd98 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSRequest.m @@ -13,7 +13,11 @@ self = [super initWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:textSecureHTTPTimeOut]; - self.parameters = [NSMutableDictionary dictionary]; + if (!self) { + return nil; + } + + self.parameters = @{}; return self; } @@ -33,11 +37,14 @@ return nil; } -#pragma clang diagnostic pop - -- (void)makeAuthenticatedRequest { - OWSAssert([TSAccountManager serverAuthToken]); - [self.parameters addEntriesFromDictionary:@{ @"Authorization" : [TSAccountManager serverAuthToken] }]; ++ (instancetype)requestWithUrl:(NSURL *)url + method:(NSString *)method + parameters:(NSDictionary *)parameters +{ + TSRequest *request = [[TSRequest alloc] initWithURL:url]; + [request setHTTPMethod:method]; + request.parameters = parameters; + return request; } @end diff --git a/SignalServiceKit/src/Network/API/Requests/TSRequestVerificationCodeRequest.m b/SignalServiceKit/src/Network/API/Requests/TSRequestVerificationCodeRequest.m index 56812af34..a73a1236a 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSRequestVerificationCodeRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSRequestVerificationCodeRequest.m @@ -12,6 +12,9 @@ textSecureAccountsAPI, [self stringForTransport:transport], phoneNumber]]]; + if (!self) { + return nil; + } self.parameters = nil; [self setHTTPMethod:@"GET"]; @@ -30,7 +33,4 @@ } } -- (void)makeAuthenticatedRequest { -} - @end diff --git a/SignalServiceKit/src/Network/API/Requests/TSSubmitMessageRequest.m b/SignalServiceKit/src/Network/API/Requests/TSSubmitMessageRequest.m index 15f22c680..4fa5119ad 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSSubmitMessageRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSSubmitMessageRequest.m @@ -1,14 +1,9 @@ // -// TSSubmitMessageRequest.m -// TextSecureiOS +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -// Created by Christine Corbett Moran on 11/30/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" #import "TSSubmitMessageRequest.h" +#import "TSConstants.h" @implementation TSSubmitMessageRequest @@ -18,17 +13,21 @@ timeStamp:(uint64_t)timeStamp { self = [super initWithURL:[NSURL URLWithString:[textSecureMessagesAPI stringByAppendingString:contactRegisteredID]]]; + if (!self) { + return nil; + } - NSMutableDictionary *allMessages = - [@{ @"messages" : messages, - @"timestamp" : [NSNumber numberWithUnsignedLongLong:timeStamp] } mutableCopy]; + NSMutableDictionary *parameters = [@{ + @"messages" : messages, + @"timestamp" : @(timeStamp), + } mutableCopy]; if (relay) { - [allMessages setObject:relay forKey:@"relay"]; + parameters[@"relay"] = relay; } [self setHTTPMethod:@"PUT"]; - [self setParameters:allMessages]; + self.parameters = parameters; return self; } diff --git a/SignalServiceKit/src/Network/API/Requests/TSUpdateAttributesRequest.m b/SignalServiceKit/src/Network/API/Requests/TSUpdateAttributesRequest.m index caf6c4dd3..a672ede3d 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSUpdateAttributesRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSUpdateAttributesRequest.m @@ -1,10 +1,10 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // +#import "TSUpdateAttributesRequest.h" #import "TSAttributes.h" #import "TSConstants.h" -#import "TSUpdateAttributesRequest.h" NS_ASSUME_NONNULL_BEGIN @@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN if (self) { [self setHTTPMethod:@"PUT"]; - [self.parameters addEntriesFromDictionary:[TSAttributes attributesFromStorageWithManualMessageFetching:enableManualMessageFetching]]; + self.parameters = [TSAttributes attributesFromStorageWithManualMessageFetching:enableManualMessageFetching]; } return self; diff --git a/SignalServiceKit/src/Network/API/Requests/TSVerifyCodeRequest.m b/SignalServiceKit/src/Network/API/Requests/TSVerifyCodeRequest.m index ed7e6bdfa..309132c74 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSVerifyCodeRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSVerifyCodeRequest.m @@ -1,11 +1,11 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // +#import "TSVerifyCodeRequest.h" #import "TSAccountManager.h" #import "TSAttributes.h" #import "TSConstants.h" -#import "TSVerifyCodeRequest.h" @implementation TSVerifyCodeRequest @@ -17,11 +17,10 @@ initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/code/%@", textSecureAccountsAPI, verificationCode]]]; - NSDictionary *attributes = - [TSAttributes attributesWithSignalingKey:signalingKey serverAuthToken:authKey manualMessageFetching:NO]; - _numberToValidate = phoneNumber; - [self.parameters addEntriesFromDictionary:attributes]; + + self.parameters = + [TSAttributes attributesWithSignalingKey:signalingKey serverAuthToken:authKey manualMessageFetching:NO]; [self setHTTPMethod:@"PUT"]; diff --git a/SignalServiceKit/src/Network/API/TSNetworkManager.m b/SignalServiceKit/src/Network/API/TSNetworkManager.m index 686fb9957..058385c5b 100644 --- a/SignalServiceKit/src/Network/API/TSNetworkManager.m +++ b/SignalServiceKit/src/Network/API/TSNetworkManager.m @@ -98,8 +98,9 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error); [sessionManager.requestSerializer setAuthorizationHeaderFieldWithUsername:((TSVerifyCodeRequest *)request).numberToValidate password:[request.parameters objectForKey:@"AuthKey"]]; - [request.parameters removeObjectForKey:@"AuthKey"]; - [sessionManager PUT:request.URL.absoluteString parameters:request.parameters success:success failure:failure]; + NSMutableDictionary *parameters = [request.parameters mutableCopy]; + [parameters removeObjectForKey:@"AuthKey"]; + [sessionManager PUT:request.URL.absoluteString parameters:parameters success:success failure:failure]; } else { if (![request isKindOfClass:[TSRequestVerificationCodeRequest class]]) { [sessionManager.requestSerializer diff --git a/SignalServiceKit/src/TSConstants.h b/SignalServiceKit/src/TSConstants.h index 6b9e06dc2..1f82b5d17 100644 --- a/SignalServiceKit/src/TSConstants.h +++ b/SignalServiceKit/src/TSConstants.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #ifndef TextSecureKit_Constants_h @@ -20,20 +20,20 @@ typedef NS_ENUM(NSInteger, TSWhisperMessageType) { //#ifndef DEBUG // Production -#define textSecureWebSocketAPI @"wss://textsecure-service.whispersystems.org/v1/websocket/" -#define textSecureServerURL @"https://textsecure-service.whispersystems.org/" -#define textSecureCDNServerURL @"https://cdn.signal.org" -#define textSecureServiceReflectorHost @"signal-reflector-meek.appspot.com" -#define textSecureCDNReflectorHost @"signal-cdn-reflector.appspot.com" +//#define textSecureWebSocketAPI @"wss://textsecure-service.whispersystems.org/v1/websocket/" +//#define textSecureServerURL @"https://textsecure-service.whispersystems.org/" +//#define textSecureCDNServerURL @"https://cdn.signal.org" +//#define textSecureServiceReflectorHost @"signal-reflector-meek.appspot.com" +//#define textSecureCDNReflectorHost @"signal-cdn-reflector.appspot.com" //#else // //// Staging -//#define textSecureWebSocketAPI @"wss://textsecure-service-staging.whispersystems.org/v1/websocket/" -//#define textSecureServerURL @"https://textsecure-service-staging.whispersystems.org/" -//#define textSecureCDNServerURL @"https://cdn-staging.signal.org" -//#define textSecureServiceReflectorHost @"meek-signal-service-staging.appspot.com"; -//#define textSecureCDNReflectorHost @"meek-signal-cdn-staging.appspot.com"; +#define textSecureWebSocketAPI @"wss://textsecure-service-staging.whispersystems.org/v1/websocket/" +#define textSecureServerURL @"https://textsecure-service-staging.whispersystems.org/" +#define textSecureCDNServerURL @"https://cdn-staging.signal.org" +#define textSecureServiceReflectorHost @"meek-signal-service-staging.appspot.com"; +#define textSecureCDNReflectorHost @"meek-signal-cdn-staging.appspot.com"; // //#endif @@ -51,6 +51,7 @@ typedef NS_ENUM(NSInteger, TSWhisperMessageType) { #define textSecureProfileAPIFormat @"v1/profile/%@" #define textSecureSetProfileNameAPIFormat @"v1/profile/name/%@" #define textSecureProfileAvatarFormAPI @"v1/profile/form/avatar" +#define textSecure2FAAPI @"/v1/accounts/pin" #define SignalApplicationGroup @"group.org.whispersystems.signal.group" diff --git a/SignalServiceKit/src/Util/OWS2FAManager.h b/SignalServiceKit/src/Util/OWS2FAManager.h new file mode 100644 index 000000000..283e78e55 --- /dev/null +++ b/SignalServiceKit/src/Util/OWS2FAManager.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^OWS2FASuccess)(void); +typedef void (^OWS2FAFailure)(NSError *error); + +// This class can be safely accessed and used from any thread. +@interface OWS2FAManager : NSObject + +- (instancetype)init NS_UNAVAILABLE; + ++ (instancetype)sharedManager; + +- (BOOL)is2FAEnabled; + +- (void)enable2FAWithPin:(NSString *)pin success:(OWS2FASuccess)success failure:(OWS2FAFailure)failure; + +- (void)disable2FAWithSuccess:(OWS2FASuccess)success failure:(OWS2FAFailure)failure; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Util/OWS2FAManager.m b/SignalServiceKit/src/Util/OWS2FAManager.m new file mode 100644 index 000000000..0061b81fb --- /dev/null +++ b/SignalServiceKit/src/Util/OWS2FAManager.m @@ -0,0 +1,105 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "OWS2FAManager.h" +#import "OWSRequestFactory.h" +#import "TSNetworkManager.h" +#import "TSStorageManager.h" +#import "YapDatabaseConnection+OWS.h" + +NS_ASSUME_NONNULL_BEGIN + +NSString *const kOWS2FAManager_Collection = @"kOWS2FAManager_Collection"; +NSString *const kOWS2FAManager_IsEnabledKey = @"kOWS2FAManager_IsEnabledKey"; + +@interface OWS2FAManager () + +@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; +@property (nonatomic, readonly) TSNetworkManager *networkManager; + +@end + +#pragma mark - + +@implementation OWS2FAManager + ++ (instancetype)sharedManager +{ + static OWS2FAManager *sharedMyManager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedMyManager = [[self alloc] initDefault]; + }); + return sharedMyManager; +} + +- (instancetype)initDefault +{ + TSStorageManager *storageManager = [TSStorageManager sharedManager]; + TSNetworkManager *networkManager = [TSNetworkManager sharedManager]; + + return [self initWithStorageManager:storageManager networkManager:networkManager]; +} + +- (instancetype)initWithStorageManager:(TSStorageManager *)storageManager + networkManager:(TSNetworkManager *)networkManager +{ + self = [super init]; + + if (!self) { + return self; + } + + OWSAssert(storageManager); + OWSAssert(networkManager); + + _dbConnection = storageManager.newDatabaseConnection; + _networkManager = networkManager; + + OWSSingletonAssert(); + + return self; +} + +- (BOOL)is2FAEnabled +{ + return [self.dbConnection boolForKey:kOWS2FAManager_IsEnabledKey + inCollection:kOWS2FAManager_Collection + defaultValue:NO]; +} + +- (void)enable2FAWithPin:(NSString *)pin success:(OWS2FASuccess)success failure:(OWS2FAFailure)failure +{ + OWSAssert(pin.length > 0); + OWSAssert(success); + OWSAssert(failure); + + TSRequest *request = [OWSRequestFactory enable2FARequestWithPin:pin]; + [self.networkManager makeRequest:request + success:^(NSURLSessionDataTask *task, id responseObject) { + success(); + } + failure:^(NSURLSessionDataTask *task, NSError *error) { + failure(error); + }]; +} + +- (void)disable2FAWithSuccess:(OWS2FASuccess)success failure:(OWS2FAFailure)failure +{ + OWSAssert(success); + OWSAssert(failure); + + TSRequest *request = [OWSRequestFactory disable2FARequest]; + [self.networkManager makeRequest:request + success:^(NSURLSessionDataTask *task, id responseObject) { + success(); + } + failure:^(NSURLSessionDataTask *task, NSError *error) { + failure(error); + }]; +} + +@end + +NS_ASSUME_NONNULL_END