diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 826f91f..1f2e363 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -15,6 +15,7 @@ PODS: - SimpleAuth (0.3.9): - SimpleAuth/BoxWeb (= 0.3.9) - SimpleAuth/Core (= 0.3.9) + - SimpleAuth/ConstantContact (= 0.3.9) - SimpleAuth/DropboxWeb (= 0.3.9) - SimpleAuth/Facebook (= 0.3.9) - SimpleAuth/FacebookWeb (= 0.3.9) @@ -36,6 +37,8 @@ PODS: - SimpleAuth/Core (0.3.9): - CMDQueryStringSerialization - ReactiveCocoa + - SimpleAuth/ConstantContact (0.3.9): + - SimpleAuth/Core - SimpleAuth/DropboxWeb (0.3.9): - SimpleAuth/Core - SimpleAuth/Facebook (0.3.9): diff --git a/Example/SimpleAuth/Providers.plist b/Example/SimpleAuth/Providers.plist index efa2451..4765ea8 100644 --- a/Example/SimpleAuth/Providers.plist +++ b/Example/SimpleAuth/Providers.plist @@ -19,5 +19,6 @@ trello-web box-web onedrive-web + constantcontact diff --git a/Example/SimpleAuth/SADAppDelegate.m b/Example/SimpleAuth/SADAppDelegate.m index 98a5cb2..bf8a34f 100644 --- a/Example/SimpleAuth/SADAppDelegate.m +++ b/Example/SimpleAuth/SADAppDelegate.m @@ -88,6 +88,9 @@ - (void)configureAuthorizaionProviders { // client_id and client_secret are required SimpleAuth.configuration[@"onedrive-web"] = @{}; + + // client_id, redirect_uri are required + SimpleAuth.configuration[@"constantcontact"] = @{}; } diff --git a/Pod/Providers/ConstantContact/SimpleAuthConstantContactConstants.h b/Pod/Providers/ConstantContact/SimpleAuthConstantContactConstants.h new file mode 100644 index 0000000..37ec970 --- /dev/null +++ b/Pod/Providers/ConstantContact/SimpleAuthConstantContactConstants.h @@ -0,0 +1,15 @@ +// +// SimpleAuthConstantContactConstants.h +// SimpleAuth +// +// Created by Tal Kain . +// Copyright (c) 2015 Fire Place Inc. All rights reserved. +// + +#ifndef SimpleAuthConstantContactConstants_h +#define SimpleAuthConstantContactConstants_h + +FOUNDATION_EXPORT NSString *const CONSTANT_CONTACT_AUTHORIZE_URI; +FOUNDATION_EXPORT NSString *const CONSTANT_CONTACT_INFO_END_POINT_URI; + +#endif /* SimpleAuthConstantContactConstants_h */ diff --git a/Pod/Providers/ConstantContact/SimpleAuthConstantContactConstants.m b/Pod/Providers/ConstantContact/SimpleAuthConstantContactConstants.m new file mode 100644 index 0000000..af5ee94 --- /dev/null +++ b/Pod/Providers/ConstantContact/SimpleAuthConstantContactConstants.m @@ -0,0 +1,12 @@ +// +// SimpleAuthConstantContactConstants.m +// SimpleAuth +// +// Created by Tal Kain . +// Copyright (c) 2015 Fire Place Inc. All rights reserved. +// + +// Based on https://developer.constantcontact.com/docs/authentication/oauth-2.0-client-flow.html + +NSString *const CONSTANT_CONTACT_AUTHORIZE_URI = @"https://oauth2.constantcontact.com/oauth2/oauth/siteowner/authorize"; +NSString *const CONSTANT_CONTACT_INFO_END_POINT_URI = @"https://api.constantcontact.com/v2/account/info"; diff --git a/Pod/Providers/ConstantContact/SimpleAuthConstantContactLoginViewController.h b/Pod/Providers/ConstantContact/SimpleAuthConstantContactLoginViewController.h new file mode 100644 index 0000000..e528d68 --- /dev/null +++ b/Pod/Providers/ConstantContact/SimpleAuthConstantContactLoginViewController.h @@ -0,0 +1,14 @@ +// +// SimpleAuthConstantContactLoginViewController.h +// SimpleAuth +// +// Created by Tal Kain . +// Based on BoxWeb's provider created by dkhamsing and FoursquareWeb's provider created by Julien Seren-Rosso +// Copyright (c) 2015 Fire Place Inc. All rights reserved. +// + +#import "SimpleAuthWebViewController.h" + +@interface SimpleAuthConstantContactLoginViewController : SimpleAuthWebViewController + +@end diff --git a/Pod/Providers/ConstantContact/SimpleAuthConstantContactLoginViewController.m b/Pod/Providers/ConstantContact/SimpleAuthConstantContactLoginViewController.m new file mode 100644 index 0000000..049dbb5 --- /dev/null +++ b/Pod/Providers/ConstantContact/SimpleAuthConstantContactLoginViewController.m @@ -0,0 +1,38 @@ +// +// SimpleAuthConstantContactLoginViewController.m +// SimpleAuth +// +// Created by Tal Kain . +// Based on BoxWeb's provider created by dkhamsing and FoursquareWeb's provider created by Julien Seren-Rosso +// Copyright (c) 2015 Fire Place Inc. All rights reserved. +// + +#import "SimpleAuthConstantContactLoginViewController.h" +#import "SimpleAuthConstantContactConstants.h" + +@implementation SimpleAuthConstantContactLoginViewController + +#pragma mark - SimpleAuthWebViewController + +- (instancetype)initWithOptions:(NSDictionary *)options requestToken:(NSDictionary *)requestToken { + if ((self = [super initWithOptions:options requestToken:requestToken])) { + self.title = @"ConstantContact"; + } + return self; +} + +- (NSURLRequest *)initialRequest { + NSDictionary *parameters = @{ + @"client_id" : self.options[@"client_id"], + @"redirect_uri" : self.options[SimpleAuthRedirectURIKey], + @"response_type" : @"token" + }; + NSString *URLString = [NSString stringWithFormat:@"%@?%@", + CONSTANT_CONTACT_AUTHORIZE_URI, + [CMDQueryStringSerialization queryStringWithDictionary:parameters]]; + NSURL *URL = [NSURL URLWithString:URLString]; + + return [NSURLRequest requestWithURL:URL]; +} + +@end diff --git a/Pod/Providers/ConstantContact/SimpleAuthConstantContactProvider.h b/Pod/Providers/ConstantContact/SimpleAuthConstantContactProvider.h new file mode 100644 index 0000000..3561045 --- /dev/null +++ b/Pod/Providers/ConstantContact/SimpleAuthConstantContactProvider.h @@ -0,0 +1,14 @@ +// +// SimpleAuthConstantContactProvider.h +// SimpleAuth +// +// Created by Tal Kain . +// Based on BoxWeb's provider created by dkhamsing and FoursquareWeb's provider created by Julien Seren-Rosso +// Copyright (c) 2015 Fire Place Inc. All rights reserved. +// + +#import "SimpleAuthProvider.h" + +@interface SimpleAuthConstantContactProvider : SimpleAuthProvider + +@end diff --git a/Pod/Providers/ConstantContact/SimpleAuthConstantContactProvider.m b/Pod/Providers/ConstantContact/SimpleAuthConstantContactProvider.m new file mode 100644 index 0000000..9331597 --- /dev/null +++ b/Pod/Providers/ConstantContact/SimpleAuthConstantContactProvider.m @@ -0,0 +1,162 @@ +// +// SimpleAuthConstantContactProvider.m +// SimpleAuth +// +// Created by Tal Kain . +// Based on BoxWeb's provider created by dkhamsing and FoursquareWeb's provider created by Julien Seren-Rosso +// Copyright (c) 2015 Fire Place Inc. All rights reserved. +// + +#import "SimpleAuthConstantContactProvider.h" +#import "SimpleAuthConstantContactLoginViewController.h" +#import "SimpleAuthConstantContactConstants.h" + +#import +#import "UIViewController+SimpleAuthAdditions.h" + +@implementation SimpleAuthConstantContactProvider + +#pragma mark - SimpleAuthProvider + ++ (NSString *)type { + return @"constantcontact"; +} + + ++ (NSDictionary *)defaultOptions { + + // Default present block + SimpleAuthInterfaceHandler presentBlock = ^(UIViewController *controller) { + UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:controller]; + navigation.modalPresentationStyle = UIModalPresentationFormSheet; + UIViewController *presented = [UIViewController SimpleAuth_presentedViewController]; + [presented presentViewController:navigation animated:YES completion:nil]; + }; + + // Default dismiss block + SimpleAuthInterfaceHandler dismissBlock = ^(id controller) { + [controller dismissViewControllerAnimated:YES completion:nil]; + }; + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithDictionary:[super defaultOptions]]; + dictionary[SimpleAuthPresentInterfaceBlockKey] = presentBlock; + dictionary[SimpleAuthDismissInterfaceBlockKey] = dismissBlock; + return dictionary; +} + + +- (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion { + [[[self accessToken] + flattenMap:^(NSDictionary *response) { + NSArray *signals = @[ + [self accountWithAccessToken:response], + [RACSignal return:response] + ]; + return [self rac_liftSelector:@selector(dictionaryWithAccount:accessToken:) withSignalsFromArray:signals]; + }] + subscribeNext:^(NSDictionary *response) { + completion(response, nil); + } + error:^(NSError *error) { + completion(nil, error); + }]; +} + +#pragma mark - Private + + +- (RACSignal *)accessToken { + return [RACSignal createSignal:^RACDisposable *(id subscriber) { + dispatch_async(dispatch_get_main_queue(), ^{ + SimpleAuthConstantContactLoginViewController *login = [[SimpleAuthConstantContactLoginViewController alloc] initWithOptions:self.options]; + login.completion = ^(UIViewController *login, NSURL *URL, NSError *error) { + SimpleAuthInterfaceHandler dismissBlock = self.options[SimpleAuthDismissInterfaceBlockKey]; + dismissBlock(login); + + // Parse URL + NSString *fragment = [URL fragment]; + NSDictionary *dictionary = [CMDQueryStringSerialization dictionaryWithQueryString:fragment]; + NSString *token = dictionary[@"access_token"]; + + // Check for error + if (![token length]) { + [subscriber sendError:error]; + return; + } + + // Send completion + [subscriber sendNext:token]; + [subscriber sendCompleted]; + }; + + SimpleAuthInterfaceHandler block = self.options[SimpleAuthPresentInterfaceBlockKey]; + block(login); + }); + return nil; + }]; +} + +- (RACSignal *)accountWithAccessToken:(NSDictionary *)accessToken { + return [RACSignal createSignal:^RACDisposable *(id subscriber) { + NSDictionary *parameters = @{ @"api_key" : self.options[@"client_id"] }; + NSString *query = [CMDQueryStringSerialization queryStringWithDictionary:parameters]; + NSString *URLString = [NSString stringWithFormat:@"%@?%@", CONSTANT_CONTACT_INFO_END_POINT_URI, query]; + + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString]]; + NSString *oauthCode = [NSString stringWithFormat:@"Bearer %@", accessToken]; + [request setValue:oauthCode forHTTPHeaderField:@"Authorization"]; + [NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue + completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 99)]; + NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; + if ([indexSet containsIndex:statusCode] && data) { + NSError *parseError = nil; + NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError]; + if (dictionary) { + [subscriber sendNext:dictionary]; + [subscriber sendCompleted]; + } + else { + [subscriber sendError:parseError]; + } + } + else { + [subscriber sendError:connectionError]; + } + }]; + return nil; + }]; +} + + +- (NSDictionary *)dictionaryWithAccount:(NSDictionary *)account accessToken:(NSDictionary *)accessToken { + NSMutableDictionary *dictionary = [NSMutableDictionary new]; + + // Provider + dictionary[@"provider"] = [[self class] type]; + + // Credentials + dictionary[@"credentials"] = @{ + @"token" : accessToken, + @"type" : @"token", + }; + + // User ID + dictionary[@"id"] = account[@"email"]; + + // Raw response + dictionary[@"extra"] = @{ + @"raw_info" : account + }; + + // User info + NSMutableDictionary *user = [NSMutableDictionary new]; + user[@"login"] = account[@"email"]; + user[@"name"] = [NSString stringWithFormat:@"%@ %@", account[@"first_name"], account[@"last_name"]]; + user[@"phone"] = account[@"phone"]; + dictionary[@"info"] = user; + + return dictionary; +} + +@end diff --git a/SimpleAuth.podspec b/SimpleAuth.podspec index 6125ab9..685ef4c 100755 --- a/SimpleAuth.podspec +++ b/SimpleAuth.podspec @@ -128,4 +128,9 @@ Pod::Spec.new do |s| ss.private_header_files = 'Pod/Providers/OneDriveWeb/*.h' end + s.subspec 'ConstantContact' do |ss| + ss.dependency 'SimpleAuth/Core' + ss.source_files = 'Pod/Providers/ConstantContact' + ss.private_header_files = 'Pod/Providers/ConstantContact/*.h' + end end