Skip to content
This repository has been archived by the owner on Aug 16, 2023. It is now read-only.

Feedly provider #58

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Providers/Facebook/SimpleAuthFacebookProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ + (NSString *)type {
+ (NSDictionary *)defaultOptions {
return @{
@"permissions" : @[ @"email" ],
@"audience" : @[ACFacebookAudienceOnlyMe]
@"audience" : @[ ACFacebookAudienceOnlyMe ]
};
}

Expand Down Expand Up @@ -124,15 +124,17 @@ - (NSDictionary *)dictionaryWithRemoteAccount:(NSDictionary *)remoteAccount syst
// User info
NSMutableDictionary *user = [NSMutableDictionary new];
user[@"nickname"] = remoteAccount[@"username"];
user[@"email"] = remoteAccount[@"email"];
if (remoteAccount[@"email"]) {
user[@"email"] = remoteAccount[@"email"];
}
user[@"name"] = remoteAccount[@"name"];
user[@"first_name"] = remoteAccount[@"first_name"];
user[@"last_name"] = remoteAccount[@"last_name"];
user[@"image"] = avatar;
if (location) {
user[@"location"] = location;
}
user[@"verified"] = remoteAccount[@"verified"];
user[@"verified"] = remoteAccount[@"verified"] ?: @NO;
user[@"urls"] = @{
@"Facebook" : remoteAccount[@"link"],
};
Expand Down
6 changes: 4 additions & 2 deletions Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,17 @@ - (NSDictionary *)dictionaryWithAccount:(NSDictionary *)account accessToken:(NSD
// User info
NSMutableDictionary *user = [NSMutableDictionary new];
user[@"nickname"] = account[@"username"];
user[@"email"] = account[@"email"];
if (account[@"email"]) {
user[@"email"] = account[@"email"];
}
user[@"name"] = account[@"name"];
user[@"first_name"] = account[@"first_name"];
user[@"last_name"] = account[@"last_name"];
user[@"image"] = avatar;
if (location) {
user[@"location"] = location;
}
user[@"verified"] = account[@"verified"];
user[@"verified"] = account[@"verified"] ?: @NO;
user[@"urls"] = @{
@"Facebook" : account[@"link"],
};
Expand Down
13 changes: 13 additions & 0 deletions Providers/FeedlyWeb/SimpleAuthFeedlyWebLoginViewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SimpleAuthFeedlyWebLoginViewController.h
// SimpleAuth
//
// Created by Luís Portela Afonso on 26/02/14.
// Copyright (c) 2014 Byliner, Inc. All rights reserved.
//

#import "SimpleAuthWebViewController.h"

@interface SimpleAuthFeedlyWebLoginViewController : SimpleAuthWebViewController

@end
32 changes: 32 additions & 0 deletions Providers/FeedlyWeb/SimpleAuthFeedlyWebLoginViewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// SimpleAuthFeedlyWebLoginViewController.m
// SimpleAuth
//
// Created by Luís Portela Afonso on 26/02/14.
// Copyright (c) 2014 Byliner, Inc. All rights reserved.
//

#import "SimpleAuthFeedlyWebLoginViewController.h"

@implementation SimpleAuthFeedlyWebLoginViewController

- (id)initWithOptions:(NSDictionary *)options requestToken:(NSDictionary *)requestToken {
if ((self = [super initWithOptions:options requestToken:requestToken])) {
self.title = @"Feedly";
}
return self;
}


- (NSURLRequest *)initialRequest {
NSDictionary *parameters = @{
@"response_type" : @"code",
@"client_id" : self.options[@"client_id"],
@"redirect_uri" : self.options[@"redirect_uri"],
@"scope" : self.options[@"scope"]
};
NSString *URLString = [NSString stringWithFormat:@"http://feedly.com/v3/auth/auth?%@", [CMDQueryStringSerialization queryStringWithDictionary:parameters]];
return [NSURLRequest requestWithURL:[NSURL URLWithString:URLString]];
}

@end
13 changes: 13 additions & 0 deletions Providers/FeedlyWeb/SimpleAuthFeedlyWebProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SimpleAuthFeedlyWebProvider.h
// SimpleAuth
//
// Created by Luís Portela Afonso on 26/02/14.
// Copyright (c) 2014 Byliner, Inc. All rights reserved.
//

#import "SimpleAuthProvider.h"

@interface SimpleAuthFeedlyWebProvider : SimpleAuthProvider

@end
184 changes: 184 additions & 0 deletions Providers/FeedlyWeb/SimpleAuthFeedlyWebProvider.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
//
// SimpleAuthFeedlyWebProvider.m
// SimpleAuth
//
// Created by Luís Portela Afonso on 26/02/14.
// Copyright (c) 2014 Byliner, Inc. All rights reserved.
//

#import "SimpleAuthFeedlyWebProvider.h"
#import "SimpleAuthFeedlyWebLoginViewController.h"
#import "UIViewController+SimpleAuthAdditions.h"

#import <ReactiveCocoa/ReactiveCocoa.h>

@implementation SimpleAuthFeedlyWebProvider

#pragma mark - SimpleAuthProvider

+ (NSString *)type {
return @"feedly-web";
}


+ (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;
dictionary[@"scope"] = @"https://cloud.feedly.com/subscriptions";
return dictionary;
}


- (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion {
[[[[self authenticationCode]
flattenMap:^(NSString *code) {
return [self accessTokenWithAuthenticationCode:code];
}]
flattenMap:^(NSDictionary *accessToken) {
NSArray *signals = @[
[RACSignal return:accessToken],
[self accountWithAccessToken:accessToken]
];
return [self rac_liftSelector:@selector(dictionaryWithAccessTokenResponse:accountResponse:) withSignalsFromArray:signals];
}]
subscribeNext:^(NSDictionary *dictionary) {
completion(dictionary, nil);
}
error:^(NSError *error) {
completion(nil, error);
}];
}


#pragma mark - Private

- (RACSignal*)authenticationCode {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
dispatch_async(dispatch_get_main_queue(), ^{
SimpleAuthFeedlyWebLoginViewController *login = [[SimpleAuthFeedlyWebLoginViewController alloc] initWithOptions:self.options];
login.completion = ^(UIViewController *controller, NSURL *URL, NSError *error) {
SimpleAuthInterfaceHandler block = self.options[SimpleAuthDismissInterfaceBlockKey];
block(controller);

// Parse URL
NSString *query = [URL query];
NSDictionary *dictionary = [CMDQueryStringSerialization dictionaryWithQueryString:query];
id code = dictionary[@"code"];

// Check for error
if (!code) {
[subscriber sendError:error];
return ;
}

// Send completion
[subscriber sendNext:@"code"];
[subscriber sendCompleted];
};

SimpleAuthInterfaceHandler block = self.options[SimpleAuthPresentInterfaceBlockKey];
block(login);
});
return nil;
}];
}


- (RACSignal *)accessTokenWithAuthenticationCode:(NSString *)code {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

// Build request
NSDictionary *parameters = @{
@"code" : code,
@"client_id" : self.options[@"client_id"],
@"client_secret" : self.options[@"client_secret"],
@"redirect_uri" : self.options[@"redirect_uri"],
@"grant_type" : @"authorization_code",
};
NSData *POSTBody = [NSJSONSerialization dataWithJSONObject:parameters options:kNilOptions error:nil];
NSURL *URL = [NSURL URLWithString:@"http://feedly.com/v3/auth/token"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:POSTBody];

// Run request
[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
return nil;
}];
}


- (RACSignal *)accountWithAccessToken:(NSDictionary *)accessToken {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}];
}


- (NSDictionary *)dictionaryWithAccessTokenResponse:(NSDictionary *)accessToken accountResponse:(NSDictionary *)account {
NSMutableDictionary *dictionary = [NSMutableDictionary new];

// Provider
dictionary[@"provider"] = [[self class] type];

// Credentials
NSTimeInterval expiresAtInterval = [accessToken[@"expires_in"] doubleValue];
NSDate *expiresAtDate = [NSDate dateWithTimeIntervalSinceNow:expiresAtInterval];
dictionary[@"credentials"] = @{
@"token" : accessToken[@"access_token"],
@"expires_at" : expiresAtDate,
@"type" : accessToken[@"token_type"],
@"refresh" : accessToken[@"refresh_token"]
};

// User ID
dictionary[@"uid"] = accessToken[@"id"];

// User info
NSMutableDictionary *user = [NSMutableDictionary new];
user[@"plan"] = accessToken[@"plan"];
dictionary[@"info"] = user;

return dictionary;
}

@end
20 changes: 20 additions & 0 deletions SimpleAuth.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
1B766AE718C34D2400F77FA8 /* SimpleAuthFeedlyWebLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B766AE418C34D2400F77FA8 /* SimpleAuthFeedlyWebLoginViewController.m */; };
1B766AE818C34D2400F77FA8 /* SimpleAuthFeedlyWebProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B766AE618C34D2400F77FA8 /* SimpleAuthFeedlyWebProvider.m */; };
3B35369A1894C5710044EA0E /* ACAccountStore+SimpleAuth.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3536991894C5710044EA0E /* ACAccountStore+SimpleAuth.m */; };
3B52BB911887088400C73329 /* SimpleAuthTwitterProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B52BB901887088400C73329 /* SimpleAuthTwitterProvider.m */; };
3B52BB9518871F6200C73329 /* SimpleAuthFacebookProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B52BB9418871F6200C73329 /* SimpleAuthFacebookProvider.m */; };
Expand Down Expand Up @@ -58,6 +60,10 @@
/* Begin PBXFileReference section */
0D4998CFA03844FB99EE78AA /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
0FCEF85A832046CDB0CCBF25 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = "<group>"; };
1B766AE318C34D2400F77FA8 /* SimpleAuthFeedlyWebLoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleAuthFeedlyWebLoginViewController.h; sourceTree = "<group>"; };
1B766AE418C34D2400F77FA8 /* SimpleAuthFeedlyWebLoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleAuthFeedlyWebLoginViewController.m; sourceTree = "<group>"; };
1B766AE518C34D2400F77FA8 /* SimpleAuthFeedlyWebProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleAuthFeedlyWebProvider.h; sourceTree = "<group>"; };
1B766AE618C34D2400F77FA8 /* SimpleAuthFeedlyWebProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleAuthFeedlyWebProvider.m; sourceTree = "<group>"; };
3B3536981894C5710044EA0E /* ACAccountStore+SimpleAuth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ACAccountStore+SimpleAuth.h"; sourceTree = "<group>"; };
3B3536991894C5710044EA0E /* ACAccountStore+SimpleAuth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ACAccountStore+SimpleAuth.m"; sourceTree = "<group>"; };
3B52BB8F1887088400C73329 /* SimpleAuthTwitterProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleAuthTwitterProvider.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -151,9 +157,21 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
1B766AE218C34D2400F77FA8 /* FeedlyWeb */ = {
isa = PBXGroup;
children = (
1B766AE318C34D2400F77FA8 /* SimpleAuthFeedlyWebLoginViewController.h */,
1B766AE418C34D2400F77FA8 /* SimpleAuthFeedlyWebLoginViewController.m */,
1B766AE518C34D2400F77FA8 /* SimpleAuthFeedlyWebProvider.h */,
1B766AE618C34D2400F77FA8 /* SimpleAuthFeedlyWebProvider.m */,
);
path = FeedlyWeb;
sourceTree = "<group>";
};
3B52BB8D1887088400C73329 /* Providers */ = {
isa = PBXGroup;
children = (
1B766AE218C34D2400F77FA8 /* FeedlyWeb */,
3B52BB9218871F6200C73329 /* Facebook */,
3B66656918903F4000F3BF58 /* Facebook Web */,
3B52BB8E1887088400C73329 /* Twitter */,
Expand Down Expand Up @@ -543,6 +561,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1B766AE818C34D2400F77FA8 /* SimpleAuthFeedlyWebProvider.m in Sources */,
3BC5FC701891D86A00523166 /* SimpleAuthDropboxWebProvider.m in Sources */,
3B8C408E188792A9007DC578 /* SimpleAuthTwitterWebProvider.m in Sources */,
81A50A4C189264C500D5D8AC /* SimpleAuthLinkedInWebLoginViewController.m in Sources */,
Expand All @@ -552,6 +571,7 @@
3B8C409118879347007DC578 /* SimpleAuthTwitterWebLoginViewController.m in Sources */,
3B69D1FA18C0340200E3D415 /* UIWindow+SimpleAuthAdditions.m in Sources */,
3B6584631888ABFB00D59100 /* SimpleAuthTumblrLoginViewController.m in Sources */,
1B766AE718C34D2400F77FA8 /* SimpleAuthFeedlyWebLoginViewController.m in Sources */,
3B52BB9518871F6200C73329 /* SimpleAuthFacebookProvider.m in Sources */,
3B9AB064182AC2710011FB9E /* SimpleAuthProvider.m in Sources */,
3B52BB9B188731A300C73329 /* SimpleAuthInstagramLoginViewController.m in Sources */,
Expand Down
8 changes: 8 additions & 0 deletions SimpleAuthDemo/SADAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ - (void)configureAuthorizaionProviders {

// client_id and client_secret are required
SimpleAuth.configuration[@"sinaweibo-web"] = @{};

// client_id, client_secret and redirect_uri are required
// scope it is an optional paramenter and https://cloud.feedly.com/subscriptions is used if none specified
SimpleAuth.configuration[@"feedly-web"] = @{
@"client_id":@"client_id",
@"client_secret":@"client_secret",
@"redirect_uri":@"redirect_uri",
};
}


Expand Down
3 changes: 2 additions & 1 deletion SimpleAuthDemo/SADProviderListViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ + (NSArray *)providers {
@"foursquare-web",
@"dropbox-web",
@"linkedin-web",
@"sinaweibo-web"
@"sinaweibo-web",
@"feedly-web"
];
});
return array;
Expand Down