Archive Project
This commit is contained in:
172
Notifications for YouTube/NYTAuthentication.m
Executable file
172
Notifications for YouTube/NYTAuthentication.m
Executable file
@@ -0,0 +1,172 @@
|
||||
//
|
||||
// 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
|
||||
Reference in New Issue
Block a user