88
99#import " SimpleAuthFeedlyWebProvider.h"
1010#import " SimpleAuthFeedlyWebLoginViewController.h"
11-
1211#import " UIViewController+SimpleAuthAdditions.h"
12+
1313#import < ReactiveCocoa/ReactiveCocoa.h>
1414
1515@implementation SimpleAuthFeedlyWebProvider
1616
17- + (NSString *)type
18- {
17+ #pragma mark - SimpleAuthProvider
18+
19+ + (NSString *)type {
1920 return @" feedly-web" ;
2021}
2122
22- + (NSDictionary *)defaultOptions
23- {
23+
24+ + (NSDictionary *)defaultOptions {
25+
2426 // Default present block
2527 SimpleAuthInterfaceHandler presentBlock = ^(UIViewController *controller) {
2628
@@ -38,118 +40,122 @@ + (NSDictionary *)defaultOptions
3840 NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithDictionary: [super defaultOptions ]];
3941 dictionary[SimpleAuthPresentInterfaceBlockKey] = presentBlock;
4042 dictionary[SimpleAuthDismissInterfaceBlockKey] = dismissBlock;
43+ dictionary[@" scope" ] = @" https://cloud.feedly.com/subscriptions" ;
4144 return dictionary;
4245}
4346
44- - (void )authorizeWithCompletion : (SimpleAuthRequestHandler)completion
45- {
46- [[[self authenticationCode ] flattenMap: ^(id response) {
47- NSArray *signals = @[
48- [self exchangeCodeForRefreshAndAccess: response],
49- [RACSignal return: response]
50- ];
51- return signals[0 ];
52- }]
53- subscribeNext:^(id response) {
54- completion (response, nil );
55- }
56- error:^(NSError *error) {
57- completion (nil , error);
58- }];
47+
48+ - (void )authorizeWithCompletion : (SimpleAuthRequestHandler)completion {
49+ [[[[self authenticationCode ]
50+ flattenMap: ^(NSString *code) {
51+ return [self accessTokenWithAuthenticationCode: code];
52+ }]
53+ flattenMap: ^(NSDictionary *accessToken) {
54+ NSArray *signals = @[
55+ [RACSignal return: accessToken],
56+ [self accountWithAccessToken: accessToken]
57+ ];
58+ return [self rac_liftSelector: @selector (dictionaryWithAccessTokenResponse:accountResponse: ) withSignalsFromArray: signals];
59+ }]
60+ subscribeNext: ^(NSDictionary *dictionary) {
61+ completion (dictionary, nil );
62+ }
63+ error: ^(NSError *error) {
64+ completion (nil , error);
65+ }];
5966}
6067
61- #pragma mark - Private Methods
6268
63- - (RACSignal*)authenticationCode
64- {
69+ #pragma mark - Private
70+
71+ - (RACSignal*)authenticationCode {
6572 return [RACSignal createSignal: ^RACDisposable *(id <RACSubscriber> subscriber) {
6673 dispatch_async (dispatch_get_main_queue (), ^{
67-
6874 SimpleAuthFeedlyWebLoginViewController *login = [[SimpleAuthFeedlyWebLoginViewController alloc ] initWithOptions: self .options];
69-
7075 login.completion = ^(UIViewController *controller, NSURL *URL, NSError *error) {
7176 SimpleAuthInterfaceHandler block = self.options [SimpleAuthDismissInterfaceBlockKey];
7277 block (controller);
7378
7479 // Parse URL
75- NSDictionary *dictionary = [CMDQueryStringSerialization dictionaryWithQueryString: [ URL query ] ];
76-
77- id apiError = dictionary[@" error " ];
80+ NSString *query = [URL query ];
81+ NSDictionary *dictionary = [CMDQueryStringSerialization dictionaryWithQueryString: query];
82+ id code = dictionary[@" code " ];
7883
79- // Check for error
80- if (apiError != nil )
81- {
82- [subscriber sendError: error];
83- return ;
84+ // Check for error
85+ if (!code) {
86+ [subscriber sendError: error];
87+ return ;
8488 }
85-
86- NSString *code = dictionary[@" code" ];
87- NSString *state = dictionary[@" state" ];
88-
89+
8990 // Send completion
90- [subscriber sendNext: @{ @ " code" : code, @" state " : state} ];
91- [subscriber sendCompleted ];
91+ [subscriber sendNext: @" code" ];
92+ [subscriber sendCompleted ];
9293 };
9394
9495 SimpleAuthInterfaceHandler block = self.options [SimpleAuthPresentInterfaceBlockKey];
9596 block (login);
96-
9797 });
98-
9998 return nil ;
10099 }];
101100}
102101
103- - (RACSignal*)exchangeCodeForRefreshAndAccess : (NSDictionary *)codeState
104- {
105- return [RACSignal createSignal: ^RACDisposable *(id <RACSubscriber> subscriber) {
106-
107- NSDictionary *parameters = @{
108- @" code" : codeState[@" code" ],
109- @" client_id" : self.options [@" client_id" ],
110- @" client_secret" : self.options [@" client_secret" ],
111- @" redirect_uri" : self.options [@" redirect_uri" ],
112- @" grant_type" : @" authorization_code" ,
113- @" state" : (codeState[@" state" ] != nil ? codeState[@" state" ] : @" state.passed.in" )
114- };
115-
116- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: @" http://feedly.com/v3/auth/token" ]];
117-
118- [request setHTTPMethod: @" POST" ];
119- [request setValue: @" application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField: @" Content-Type" ];
120- [request setHTTPBody: [[CMDQueryStringSerialization queryStringWithDictionary: parameters] dataUsingEncoding: NSUTF8StringEncoding]];
102+
103+ - (RACSignal *)accessTokenWithAuthenticationCode : (NSString *)code {
104+ return [RACSignal createSignal: ^RACDisposable *(id <RACSubscriber> subscriber) {
121105
122- [NSURLConnection sendAsynchronousRequest: request queue: self .operationQueue completionHandler: ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
123-
124- if (connectionError != nil )
125- {
126- [subscriber sendError: connectionError];
127- }
128- else
129- {
130-
131- NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange (200 , 99 )];
132- NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode ];
133- if ([indexSet containsIndex: statusCode] && data)
134- {
135- __weak NSError *parseError = nil ;
136- __weak NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData: data options: kNilOptions error: &parseError];
137-
138- if (parseError != nil )
139- {
140- [subscriber sendError: parseError];
141- }
142- else
143- {
144- [subscriber sendNext: dictionary];
145- [subscriber sendCompleted ];
146- }
147- }
148- }
149- }];
106+ // Build request
107+ NSDictionary *parameters = @{
108+ @" code" : code,
109+ @" client_id" : self.options [@" client_id" ],
110+ @" client_secret" : self.options [@" client_secret" ],
111+ @" redirect_uri" : self.options [@" redirect_uri" ],
112+ @" grant_type" : @" authorization_code" ,
113+ };
114+ NSData *POSTBody = [NSJSONSerialization dataWithJSONObject: parameters options: kNilOptions error: nil ];
115+ NSURL *URL = [NSURL URLWithString: @" http://feedly.com/v3/auth/token" ];
116+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: URL];
117+ [request setHTTPMethod: @" POST" ];
118+ [request setValue: @" application/json" forHTTPHeaderField: @" Content-Type" ];
119+ [request setHTTPBody: POSTBody];
150120
121+ // Run request
122+ [NSURLConnection sendAsynchronousRequest: request queue: self .operationQueue
123+ completionHandler: ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
124+ NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange (200 , 99 )];
125+ NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode ];
126+ if ([indexSet containsIndex: statusCode] && data) {
127+ NSError *parseError = nil ;
128+ NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData: data options: kNilOptions error: &parseError];
129+ if (dictionary) {
130+ [subscriber sendNext: dictionary];
131+ [subscriber sendCompleted ];
132+ }
133+ else {
134+ [subscriber sendError: parseError];
135+ }
136+ }
137+ else {
138+ [subscriber sendError: connectionError];
139+ }
140+ }];
141+
142+ // Return
151143 return nil ;
152- }];
144+ }];
145+ }
146+
147+
148+ - (RACSignal *)accountWithAccessToken : (NSDictionary *)accessToken {
149+ return [RACSignal createSignal: ^RACDisposable *(id <RACSubscriber> subscriber) {
150+ [subscriber sendNext: nil ];
151+ [subscriber sendCompleted ];
152+ return nil ;
153+ }];
154+ }
155+
156+
157+ - (NSDictionary *)dictionaryWithAccessTokenResponse : (NSDictionary *)accessToken accountResponse : (NSDictionary *)account {
158+ return accessToken;
153159}
154160
155161@end
0 commit comments