173 lines
5.5 KiB
Objective-C
Executable File
173 lines
5.5 KiB
Objective-C
Executable File
//
|
|
// NYTAuthentication.m
|
|
// Notifications for YouTube
|
|
//
|
|
// Created by Kim Wittenburg on 21.07.13.
|
|
// Copyright (c) 2013 Kim Wittenburg. All rights reserved.
|
|
//
|
|
|
|
#import "NYTAuthentication.h"
|
|
|
|
// API Imports
|
|
#import "OAuth2.h"
|
|
|
|
// Core Imports
|
|
#import "NYTUser.h"
|
|
#import "NYTUtil.h"
|
|
#import "NYTUpdateManager.h"
|
|
|
|
// Google Access Constants
|
|
NSString * const DeveloperKey = @"key=AI39si6ubNmTeFzFTFz27hFn6r-51knz0_CDWvqgyL-nVKBcFWu5C_c46TWQcHTwwK9bOBlrhdlKatyEqjEnJhZd2dMB7UgFhQ";
|
|
NSString * const DeveloperKeyHTTPHeaderField = @"X-GData-Key";
|
|
NSString * const ClientID = @"908431532405.apps.googleusercontent.com";
|
|
NSString * const ClientSecret = @"hKcyoNAzEIuHZaz0pdTUBMBv";
|
|
NSString * const KeychainItemName = @"Notifications for YouTube";
|
|
|
|
@interface NYTAuthentication ()
|
|
|
|
@property (readwrite) GTMOAuth2Authentication *authentication;
|
|
@property (readwrite) NYTUser *loggedInUser;
|
|
|
|
@end
|
|
|
|
@implementation NYTAuthentication
|
|
|
|
#pragma mark *** Initialization ***
|
|
|
|
static NYTAuthentication *sharedAuthentication = nil;
|
|
|
|
+ (NYTAuthentication *)sharedAuthentication
|
|
{
|
|
if (!sharedAuthentication) {
|
|
sharedAuthentication = [[self alloc] init];
|
|
}
|
|
return sharedAuthentication;
|
|
}
|
|
|
|
- (id)init
|
|
{
|
|
// Allow exactly one instance at all (for any way of initialization)
|
|
if (sharedAuthentication) {
|
|
return sharedAuthentication;
|
|
}
|
|
self = [super init];
|
|
if (self) {
|
|
sharedAuthentication = self;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
#pragma mark *** KVO/KVC Additions to Properties ***
|
|
|
|
+ (NSSet *)keyPathsForValuesAffectingIsLoggedIn
|
|
{
|
|
return [NSSet setWithObjects:@"authentication", nil];
|
|
}
|
|
|
|
#pragma mark *** Login ***
|
|
|
|
- (void)tryLoginFromKeychainWithCompletionHandler:(void(^)(void))handler
|
|
{
|
|
// Get keychain data
|
|
GTMOAuth2Authentication *auth = [GTMOAuth2WindowController authForGoogleFromKeychainForName:KeychainItemName clientID:ClientID clientSecret:ClientSecret];
|
|
if (auth.canAuthorize) {
|
|
// Possible success (keychain)
|
|
// Login (to refresh tokens/validate values) in background
|
|
dispatch_queue_t prevQueue = dispatch_get_current_queue();
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
// Try logging in
|
|
NSError *error = [self completeLoginWithAuthentication:auth];
|
|
dispatch_async(prevQueue, ^{
|
|
if (!error) {
|
|
// We suceeded so update the authentication object properly
|
|
self.authentication = auth;
|
|
// Refresh the feeds without notifications to set the 'known' state
|
|
[[NYTUpdateManager sharedManager] refreshFeedsWithErrorHandler:NULL notify:NO];
|
|
}
|
|
if (handler) {
|
|
handler();
|
|
}
|
|
});
|
|
});
|
|
} else {
|
|
// Failed (keychain)
|
|
if (handler) {
|
|
handler();
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)beginLoginSheetForWindow:(NSWindow *)window completionHandler:(void (^)(NSError *))handler
|
|
{
|
|
[[NYTUpdateManager sharedManager] pauseAutoRefreshing];
|
|
|
|
// Show the login window
|
|
GTMOAuth2WindowController *windowController = [[GTMOAuth2WindowController alloc] initWithScope:@"https://gdata.youtube.com" clientID:ClientID clientSecret:ClientSecret keychainItemName:KeychainItemName resourceBundle:nil];
|
|
[windowController signInSheetModalForWindow:window completionHandler:^(GTMOAuth2Authentication *auth, NSError *error) {
|
|
if (error) {
|
|
// If an error occured just return
|
|
if (handler) {
|
|
handler(error);
|
|
}
|
|
[[NYTUpdateManager sharedManager] resumeAutoRefreshing];
|
|
} else {
|
|
// Complete the login asynchronously (because we are very likely currently operating on the main thread)
|
|
dispatch_queue_t prevQueue = dispatch_get_current_queue();
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
// Complete the login
|
|
NSError *error = [self completeLoginWithAuthentication:auth];
|
|
|
|
// Handle the error on the caller's queue
|
|
dispatch_async(prevQueue, ^{
|
|
if (!error) {
|
|
self.authentication = auth;
|
|
[[NYTUpdateManager sharedManager] refreshFeedsWithErrorHandler:NULL notify:NO];
|
|
}
|
|
if (handler) {
|
|
handler(error);
|
|
}
|
|
[[NYTUpdateManager sharedManager] resumeAutoRefreshing];
|
|
});
|
|
});
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (NSError *)completeLoginWithAuthentication:(GTMOAuth2Authentication *)auth
|
|
{
|
|
// Get the user's data
|
|
NSError *error;
|
|
static NSString *userPageURL = @"https://gdata.youtube.com/feeds/api/users/default";
|
|
NSXMLDocument *document = LoadXMLDocumentSynchronous(userPageURL, auth, &error);
|
|
if (!document) {
|
|
return error;
|
|
}
|
|
|
|
// Parse the data and store them app-friendly
|
|
NYTUser *user = [[NYTUser alloc] initWithUserProfilePage:document];
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
// Set on the main queue due to bindings relations
|
|
self.loggedInUser = user;
|
|
});
|
|
return nil;
|
|
}
|
|
|
|
#pragma mark *** Logout ***
|
|
|
|
- (void)discardLogin
|
|
{
|
|
// Also remove from keychain
|
|
[GTMOAuth2WindowController removeAuthFromKeychainForName:KeychainItemName];
|
|
self.authentication = nil;
|
|
self.loggedInUser = nil;
|
|
}
|
|
|
|
#pragma mark *** Login Information ***
|
|
|
|
- (BOOL)isLoggedIn
|
|
{
|
|
return self.authentication != nil && self.authentication.canAuthorize;
|
|
}
|
|
|
|
@end
|