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

Dribbble implementation #98

Open
wants to merge 2 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
1 change: 1 addition & 0 deletions Example/SimpleAuth/Providers.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
<string>trello-web</string>
<string>box-web</string>
<string>onedrive-web</string>
<string>dribbble</string>
</array>
</plist>
3 changes: 3 additions & 0 deletions Example/SimpleAuth/SADAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ - (void)configureAuthorizaionProviders {

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

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


Expand Down
13 changes: 13 additions & 0 deletions Pod/Providers/Dribbble/SimpleAuthDribbbleLoginViewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SimpleAuthDribbbleLoginViewController.h
// SimpleAuth
//
// Created by Martin Pilch on 21/4/15.
// Copyright (c) 2015 Martin Pilch, All rights reserved.
//

#import "SimpleAuthWebViewController.h"

@interface SimpleAuthDribbbleLoginViewController : SimpleAuthWebViewController

@end
37 changes: 37 additions & 0 deletions Pod/Providers/Dribbble/SimpleAuthDribbbleLoginViewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// SimpleAuthDribbbleLoginViewController.m
// SimpleAuthInstagram
//
// Created by Martin Pilch on 21/4/15.
// Copyright (c) 2015 Martin Pilch, All rights reserved.
//

#import "SimpleAuthDribbbleLoginViewController.h"

@implementation SimpleAuthDribbbleLoginViewController

#pragma mark - SimpleAuthWebViewController

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

- (NSURLRequest *)initialRequest {
NSMutableDictionary *parameters = [NSMutableDictionary new];
parameters[@"client_id"] = self.options[@"client_id"];
parameters[@"redirect_uri"] = self.options[SimpleAuthRedirectURIKey];
if (self.options[@"scope"]) {
parameters[@"scope"] = [self.options[@"scope"] componentsJoinedByString:@" "];
}
NSString *URLString = [NSString stringWithFormat:
@"https://dribbble.com/oauth/authorize?%@",
[CMDQueryStringSerialization queryStringWithDictionary:parameters]];
NSURL *URL = [NSURL URLWithString:URLString];

return [NSURLRequest requestWithURL:URL];
}

@end
13 changes: 13 additions & 0 deletions Pod/Providers/Dribbble/SimpleAuthDribbbleProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SimpleAuthDribbbleProvider.h
// SimpleAuth
//
// Created by Martin Pilch on 21/4/15.
// Copyright (c) 2015 Martin Pilch, All rights reserved.
//

#import "SimpleAuthProvider.h"

@interface SimpleAuthDribbbleProvider : SimpleAuthProvider

@end
206 changes: 206 additions & 0 deletions Pod/Providers/Dribbble/SimpleAuthDribbbleProvider.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
//
// SimpleAuthDribbbleProvider.m
// SimpleAuth
//
// Created by Martin Pilch on 21/4/15.
// Copyright (c) 2015 Martin Pilch, All rights reserved.
//

#import "SimpleAuthDribbbleProvider.h"
#import "SimpleAuthDribbbleLoginViewController.h"

#import "UIViewController+SimpleAuthAdditions.h"
#import <ReactiveCocoa/ReactiveCocoa.h>

@implementation SimpleAuthDribbbleProvider

#pragma mark - SimpleAuthProvider

+ (NSString *)type {
return @"dribbble";
}

+ (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 *options = [NSMutableDictionary dictionaryWithDictionary:[super defaultOptions]];
options[SimpleAuthPresentInterfaceBlockKey] = presentBlock;
options[SimpleAuthDismissInterfaceBlockKey] = dismissBlock;
options[SimpleAuthRedirectURIKey] = @"http://";

return options;
}


- (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion {
[[[self accessToken]
flattenMap:^(id responseObject) {
NSArray *signals = @[
[self accountWithAccessToken:responseObject],
[RACSignal return:responseObject]
];
return [self rac_liftSelector:@selector(dictionaryWithAccount:accessToken:) withSignalsFromArray:signals];
}]
subscribeNext:^(id responseObject) {
completion(responseObject, nil);
}
error:^(NSError *error) {
completion(nil, error);
}];
}

#pragma mark - Private

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

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

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

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

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


- (RACSignal *)accessTokenWithAuthorizationCode:(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[SimpleAuthRedirectURIKey],
};
NSString *query = [CMDQueryStringSerialization queryStringWithDictionary:parameters];
NSURL *URL = [NSURL URLWithString:@"https://dribbble.com/oauth/token"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
request.HTTPMethod = @"POST";
request.HTTPBody = [query dataUsingEncoding:NSUTF8StringEncoding];

// 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 nil;
}];
}


- (RACSignal *)accessToken {
return [[self authorizationCode] flattenMap:^(id responseObject) {
return [self accessTokenWithAuthorizationCode:responseObject];
}];
}

- (RACSignal *)accountWithAccessToken:(NSDictionary *)accessToken {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSDictionary *parameters = @{
@"access_token" : accessToken[@"access_token"],
};
NSString *URLString = [NSString stringWithFormat:@"https://api.dribbble.com/v1/user?%@",
[CMDQueryStringSerialization queryStringWithDictionary:parameters]];
NSURL *URL = [NSURL URLWithString:URLString];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
[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 dictionary];

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

// Credentials
dictionary[@"credentials"] = @{@"token" : accessToken[@"access_token"]};

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

// Raw response
dictionary[@"extra"] = @{
@"raw_info" : account
};

// User info
NSMutableDictionary *user = [NSMutableDictionary new];
user[@"name"] = account[@"name"];
user[@"username"] = account[@"username"];
user[@"image"] = account[@"avatar_url"];
dictionary[@"info"] = user;

return dictionary;
}

@end
6 changes: 6 additions & 0 deletions SimpleAuth.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,10 @@ Pod::Spec.new do |s|
ss.private_header_files = 'Pod/Providers/OneDriveWeb/*.h'
end

s.subspec 'Dribbble' do |ss|
ss.dependency 'SimpleAuth/Core'
ss.source_files = 'Pod/Providers/Dribbble'
ss.private_header_files = 'Pod/Providers/Dribbble/*.h'
end

end