mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-31 23:47:01 +00:00
refactoring: move auth-logic to the authenticator
via a delegation-completionBlock-combo
This commit is contained in:
parent
6c29a72a98
commit
567b0def60
@ -13,19 +13,7 @@
|
||||
|
||||
@interface BITAuthenticationViewController : UITableViewController
|
||||
|
||||
- (instancetype) initWithApplicationIdentifier:(NSString*) encodedApplicationIdentifier
|
||||
requirePassword:(BOOL) requiresPassword
|
||||
delegate:(id<BITAuthenticationViewControllerDelegate>) delegate;
|
||||
|
||||
/**
|
||||
* must be set
|
||||
*/
|
||||
@property (nonatomic, strong) BITHockeyAppClient *hockeyAppClient;
|
||||
|
||||
/**
|
||||
* The application's id to identifiy it in the backend
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *encodedApplicationIdentifier;
|
||||
- (instancetype) initWithDelegate:(id<BITAuthenticationViewControllerDelegate>) delegate;
|
||||
|
||||
/**
|
||||
* can be set to YES to also require the users password
|
||||
@ -39,11 +27,6 @@
|
||||
* defaults to YES
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL showsCancelButton;
|
||||
/**
|
||||
* TODO: instead of passing the whole authenticator, we actually only need
|
||||
* something to create and enqueue BITHTTPOperations
|
||||
*/
|
||||
@property (nonatomic, weak) BITAuthenticator *authenticator;
|
||||
|
||||
@property (nonatomic, weak) id<BITAuthenticationViewControllerDelegate> delegate;
|
||||
|
||||
@ -51,7 +34,27 @@
|
||||
|
||||
@protocol BITAuthenticationViewControllerDelegate<NSObject>
|
||||
|
||||
/**
|
||||
* called then the user cancelled
|
||||
*
|
||||
* @param viewController the delegating viewcontroller
|
||||
*/
|
||||
- (void) authenticationViewControllerDidCancel:(UIViewController*) viewController;
|
||||
- (void) authenticationViewController:(UIViewController*) viewController authenticatedWithToken:(NSString*) token;
|
||||
|
||||
/**
|
||||
* called when the user wants to login
|
||||
*
|
||||
* @param viewController the delegating viewcontroller
|
||||
* @param email the content of the email-field
|
||||
* @param password the content of the password-field (if existent)
|
||||
* @param completion Must be called by the delegate once the auth-task completed
|
||||
* This viewcontroller shows an activity-indicator in between and blocks
|
||||
* the UI. if succeeded is NO, it shows an alertView presenting the error
|
||||
* given by the completion block
|
||||
*/
|
||||
- (void) authenticationViewController:(UIViewController*) viewController
|
||||
handleAuthenticationWithEmail:(NSString*) email
|
||||
password:(NSString*) password
|
||||
completion:(void(^)(BOOL succeeded, NSError *error)) completion;
|
||||
|
||||
@end
|
||||
|
@ -23,14 +23,10 @@
|
||||
|
||||
@implementation BITAuthenticationViewController
|
||||
|
||||
- (instancetype) initWithApplicationIdentifier:(NSString*) encodedApplicationIdentifier
|
||||
requirePassword:(BOOL) requiresPassword
|
||||
delegate:(id<BITAuthenticationViewControllerDelegate>) delegate {
|
||||
- (instancetype) initWithDelegate:(id<BITAuthenticationViewControllerDelegate>)delegate {
|
||||
self = [super initWithStyle:UITableViewStyleGrouped];
|
||||
if (self) {
|
||||
self.title = BITHockeyLocalizedString(@"HockeyAuthenticatorViewControllerTitle");
|
||||
_encodedApplicationIdentifier = [encodedApplicationIdentifier copy];
|
||||
_requirePassword = requiresPassword;
|
||||
_delegate = delegate;
|
||||
_showsCancelButton = YES;
|
||||
}
|
||||
@ -222,71 +218,25 @@
|
||||
|
||||
- (void)saveAction:(id)sender {
|
||||
[self showLoginUI:YES];
|
||||
NSParameterAssert(self.encodedApplicationIdentifier);
|
||||
|
||||
|
||||
NSString *authenticationPath = [self authenticationPath];
|
||||
NSDictionary *params = [self parametersForAuthentication];
|
||||
|
||||
__weak typeof (self) weakSelf = self;
|
||||
[self.hockeyAppClient postPath:authenticationPath
|
||||
parameters:params
|
||||
completion:^(BITHTTPOperation *operation, id response, NSError *error) {
|
||||
typeof (self) strongSelf = weakSelf;
|
||||
if(nil == response) {
|
||||
//TODO think about alertview messages
|
||||
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
|
||||
message:@"Failed to authenticate"
|
||||
delegate:nil
|
||||
cancelButtonTitle:BITHockeyLocalizedString(@"OK")
|
||||
otherButtonTitles:nil];
|
||||
[alert show];
|
||||
} else if(401 == operation.response.statusCode) {
|
||||
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
|
||||
message:@"Not authorized"
|
||||
delegate:nil
|
||||
cancelButtonTitle:BITHockeyLocalizedString(@"OK")
|
||||
otherButtonTitles:nil];
|
||||
[alert show];
|
||||
} else {
|
||||
NSError *authParseError = nil;
|
||||
NSString *authToken = [strongSelf.class authenticationTokenFromReponse:response
|
||||
error:&authParseError];
|
||||
if(nil == authToken) {
|
||||
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
|
||||
message:@"Failed to authenticate"
|
||||
delegate:nil
|
||||
cancelButtonTitle:BITHockeyLocalizedString(@"OK")
|
||||
otherButtonTitles:nil];
|
||||
[alert show];
|
||||
} else {
|
||||
[strongSelf.delegate authenticationViewController:strongSelf authenticatedWithToken:authToken];
|
||||
}
|
||||
}
|
||||
[self showLoginUI:NO];
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSDictionary *) parametersForAuthentication {
|
||||
if(self.requirePassword) {
|
||||
return @{ @"user" : [NSString stringWithFormat:@"%@:%@", self.email, self.password] };
|
||||
} else {
|
||||
NSString *authCode = BITHockeyMD5([NSString stringWithFormat:@"%@%@",
|
||||
self.authenticator.authenticationSecret ? : @"",
|
||||
self.email ? : @""]);
|
||||
return @{
|
||||
@"email" : self.email,
|
||||
@"authcode" : authCode.lowercaseString,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *) authenticationPath {
|
||||
if(self.requirePassword) {
|
||||
return [NSString stringWithFormat:@"api/3/apps/%@/identity/authorize", self.encodedApplicationIdentifier];
|
||||
} else {
|
||||
return [NSString stringWithFormat:@"api/3/apps/%@/identity/check", self.encodedApplicationIdentifier];
|
||||
}
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[self.delegate authenticationViewController:self
|
||||
handleAuthenticationWithEmail:self.email
|
||||
password:self.password
|
||||
completion:^(BOOL succeeded, NSError *error) {
|
||||
if(succeeded) {
|
||||
//controller shoud dismiss us shortly..
|
||||
} else {
|
||||
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
|
||||
message:error.localizedDescription
|
||||
delegate:nil
|
||||
cancelButtonTitle:BITHockeyLocalizedString(@"OK")
|
||||
otherButtonTitles:nil];
|
||||
[alertView show];
|
||||
typeof(self) strongSelf = weakSelf;
|
||||
[strongSelf showLoginUI:NO];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) showLoginUI:(BOOL) enableLoginUI {
|
||||
@ -294,48 +244,4 @@
|
||||
self.tableView.userInteractionEnabled = !enableLoginUI;
|
||||
}
|
||||
|
||||
+ (NSString *) authenticationTokenFromReponse:(id) response error:(NSError **) error {
|
||||
NSParameterAssert(response);
|
||||
|
||||
NSError *jsonParseError = nil;
|
||||
id jsonObject = [NSJSONSerialization JSONObjectWithData:response
|
||||
options:0
|
||||
error:&jsonParseError];
|
||||
if(nil == jsonObject) {
|
||||
if(error) {
|
||||
*error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorAPIServerReturnedInvalidRespone
|
||||
userInfo:(jsonParseError ? @{NSUnderlyingErrorKey : jsonParseError} : nil)];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
if(![jsonObject isKindOfClass:[NSDictionary class]]) {
|
||||
if(error) {
|
||||
*error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorAPIServerReturnedInvalidRespone
|
||||
userInfo:nil];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
NSString *status = jsonObject[@"status"];
|
||||
if(nil == status) {
|
||||
if(error) {
|
||||
*error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorAPIServerReturnedInvalidRespone
|
||||
userInfo:nil];
|
||||
}
|
||||
return nil;
|
||||
} else if([status isEqualToString:@"identified"]) {
|
||||
return jsonObject[@"iuid"];
|
||||
} else if([status isEqualToString:@"authorized"]) {
|
||||
return jsonObject[@"auid"];
|
||||
} else {
|
||||
if(error) {
|
||||
*error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorNotAuthorized
|
||||
userInfo:nil];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
@ -82,6 +82,7 @@ static NSString* const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthe
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Validation
|
||||
- (void) validateInstallationWithCompletion:(tValidationCompletion) completion {
|
||||
if(nil == self.authenticationToken) {
|
||||
[self authenticateWithCompletion:^(NSString *authenticationToken, NSError *error) {
|
||||
@ -189,6 +190,8 @@ static NSString* const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthe
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Authentication
|
||||
|
||||
- (void)authenticateWithCompletion:(tAuthenticationCompletion)completion {
|
||||
if(_authenticationController) {
|
||||
BITHockeyLog(@"Already authenticating. Ignoring request");
|
||||
@ -205,10 +208,8 @@ static NSString* const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthe
|
||||
break;
|
||||
}
|
||||
|
||||
BITAuthenticationViewController *viewController = [[BITAuthenticationViewController alloc] initWithApplicationIdentifier:self.encodedAppIdentifier
|
||||
requirePassword:requiresPassword
|
||||
delegate:self];
|
||||
viewController.authenticator = self;
|
||||
BITAuthenticationViewController *viewController = [[BITAuthenticationViewController alloc] initWithDelegate:self];
|
||||
viewController.requirePassword = requiresPassword;
|
||||
switch (self.validationType) {
|
||||
case BITAuthenticatorValidationTypeNever:
|
||||
case BITAuthenticatorValidationTypeOptional:
|
||||
@ -232,6 +233,16 @@ static NSString* const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthe
|
||||
animated:YES];
|
||||
}
|
||||
|
||||
- (void) didAuthenticateWithToken:(NSString*) token {
|
||||
[_authenticationController dismissModalViewControllerAnimated:YES];
|
||||
_authenticationController = nil;
|
||||
self.authenticationToken = token;
|
||||
self.lastAuthenticatedVersion = [self executableUUID];
|
||||
if(self.authenticationCompletionBlock) {
|
||||
self.authenticationCompletionBlock(self.authenticationToken, nil);
|
||||
self.authenticationCompletionBlock = nil;
|
||||
}
|
||||
}
|
||||
#pragma mark - AuthenticationViewControllerDelegate
|
||||
- (void) authenticationViewControllerDidCancel:(UIViewController*) viewController {
|
||||
[viewController dismissModalViewControllerAnimated:YES];
|
||||
@ -247,15 +258,120 @@ static NSString* const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthe
|
||||
}
|
||||
}
|
||||
|
||||
- (void) authenticationViewController:(UIViewController*) viewController
|
||||
authenticatedWithToken:(NSString*) token {
|
||||
[viewController dismissModalViewControllerAnimated:YES];
|
||||
_authenticationController = nil;
|
||||
self.authenticationToken = token;
|
||||
self.lastAuthenticatedVersion = [self executableUUID];
|
||||
if(self.authenticationCompletionBlock) {
|
||||
self.authenticationCompletionBlock(self.authenticationToken, nil);
|
||||
self.authenticationCompletionBlock = nil;
|
||||
- (void)authenticationViewController:(UIViewController *)viewController
|
||||
handleAuthenticationWithEmail:(NSString *)email
|
||||
password:(NSString *)password
|
||||
completion:(void (^)(BOOL, NSError *))completion {
|
||||
NSParameterAssert(email && email.length);
|
||||
NSParameterAssert(self.authenticationType == BITAuthenticatorAuthTypeEmail || (password && password.length));
|
||||
NSString *authenticationPath = [self authenticationPath];
|
||||
NSDictionary *params = [self parametersForAuthenticationEmail:email password:password];
|
||||
|
||||
__weak typeof (self) weakSelf = self;
|
||||
[self.hockeyAppClient postPath:authenticationPath
|
||||
parameters:params
|
||||
completion:^(BITHTTPOperation *operation, id response, NSError *error) {
|
||||
typeof (self) strongSelf = weakSelf;
|
||||
if(nil == response) {
|
||||
NSError *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorAPIServerReturnedInvalidRespone
|
||||
userInfo:@{
|
||||
//TODO localize
|
||||
NSLocalizedDescriptionKey : @"Failed to authenticate"
|
||||
}];
|
||||
completion(NO, error);
|
||||
} else if(401 == operation.response.statusCode) {
|
||||
NSError *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorNotAuthorized
|
||||
userInfo:@{
|
||||
//TODO localize
|
||||
NSLocalizedDescriptionKey : @"Not authorized"
|
||||
}];
|
||||
completion(NO, error);
|
||||
} else {
|
||||
NSError *authParseError = nil;
|
||||
NSString *authToken = [strongSelf.class authenticationTokenFromReponse:response
|
||||
error:&authParseError];
|
||||
if(nil == authToken) {
|
||||
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
|
||||
message:@"Failed to authenticate"
|
||||
delegate:nil
|
||||
cancelButtonTitle:BITHockeyLocalizedString(@"OK")
|
||||
otherButtonTitles:nil];
|
||||
[alert show];
|
||||
} else {
|
||||
[self didAuthenticateWithToken:authToken];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
- (NSDictionary *) parametersForAuthenticationEmail:(NSString*) email password:(NSString*) password {
|
||||
if(BITAuthenticatorAuthTypeEmailAndPassword == self.authenticationType) {
|
||||
return @{ @"user" : [NSString stringWithFormat:@"%@:%@", email, password] };
|
||||
} else {
|
||||
NSString *authCode = BITHockeyMD5([NSString stringWithFormat:@"%@%@",
|
||||
self.authenticationSecret ? : @"",
|
||||
email ? : @""]);
|
||||
return @{
|
||||
@"email" : email ? : @"",
|
||||
@"authcode" : authCode.lowercaseString,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *) authenticationPath {
|
||||
if(BITAuthenticatorAuthTypeEmailAndPassword == self.authenticationType) {
|
||||
return [NSString stringWithFormat:@"api/3/apps/%@/identity/authorize", self.encodedAppIdentifier];
|
||||
} else {
|
||||
return [NSString stringWithFormat:@"api/3/apps/%@/identity/check", self.encodedAppIdentifier];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+ (NSString *) authenticationTokenFromReponse:(id) response error:(NSError **) error {
|
||||
NSParameterAssert(response);
|
||||
|
||||
NSError *jsonParseError = nil;
|
||||
id jsonObject = [NSJSONSerialization JSONObjectWithData:response
|
||||
options:0
|
||||
error:&jsonParseError];
|
||||
if(nil == jsonObject) {
|
||||
if(error) {
|
||||
*error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorAPIServerReturnedInvalidRespone
|
||||
userInfo:(jsonParseError ? @{NSUnderlyingErrorKey : jsonParseError} : nil)];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
if(![jsonObject isKindOfClass:[NSDictionary class]]) {
|
||||
if(error) {
|
||||
*error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorAPIServerReturnedInvalidRespone
|
||||
userInfo:nil];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
NSString *status = jsonObject[@"status"];
|
||||
if(nil == status) {
|
||||
if(error) {
|
||||
*error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorAPIServerReturnedInvalidRespone
|
||||
userInfo:nil];
|
||||
}
|
||||
return nil;
|
||||
} else if([status isEqualToString:@"identified"]) {
|
||||
return jsonObject[@"iuid"];
|
||||
} else if([status isEqualToString:@"authorized"]) {
|
||||
return jsonObject[@"auid"];
|
||||
} else {
|
||||
if(error) {
|
||||
*error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
|
||||
code:BITAuthenticatorNotAuthorized
|
||||
userInfo:nil];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,9 @@
|
||||
*/
|
||||
- (void) authenticateWithCompletion:(tAuthenticationCompletion) completion;
|
||||
|
||||
#pragma mark - Internal Auth callbacks
|
||||
- (void) didAuthenticateWithToken:(NSString*) token;
|
||||
|
||||
#pragma mark - Validation
|
||||
/**
|
||||
* Validate the app installation
|
||||
|
@ -150,7 +150,7 @@ static void *kInstallationIdentification = &kInstallationIdentification;
|
||||
//this will prepare everything and show the viewcontroller
|
||||
[_sut authenticateWithCompletion:nil];
|
||||
//fake delegate call from the viewcontroller
|
||||
[_sut authenticationViewController:nil authenticatedWithToken:@"SuperToken"];
|
||||
[_sut didAuthenticateWithToken:@"SuperToken"];
|
||||
|
||||
assertThat(_sut.authenticationToken, equalTo(@"SuperToken"));
|
||||
}
|
||||
@ -163,7 +163,7 @@ static void *kInstallationIdentification = &kInstallationIdentification;
|
||||
[_sut authenticateWithCompletion:^(NSString *authenticationToken, NSError *error) {
|
||||
if(authenticationToken) didAuthenticate = YES;
|
||||
}];
|
||||
[_sut authenticationViewController:nil authenticatedWithToken:@"SuperToken"];
|
||||
[_sut didAuthenticateWithToken:@"SuperToken"];
|
||||
|
||||
assertThatBool(didAuthenticate, equalToBool(YES));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user