diff --git a/Examples/iOSExplorer/iOSExplorer/ODXAppDelegate.m b/Examples/iOSExplorer/iOSExplorer/ODXAppDelegate.m index ba310e9..0e1a437 100644 --- a/Examples/iOSExplorer/iOSExplorer/ODXAppDelegate.m +++ b/Examples/iOSExplorer/iOSExplorer/ODXAppDelegate.m @@ -37,19 +37,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( // Uncomment the correct call to test with ActiveDirectory or both types of apps. [ODClient setMicrosoftAccountAppId:@"0000000048160AF8" scopes:@[@"onedrive.readwrite"] ]; - //[ODClient setActiveDirectoryAppId: - // scopes: - // redirectURL: - // flags:@{"NoThumbnails" : @(YES) }]; - // - - //[ODClient setMicrosoftAccountAppId: - // microsoftAccountScopes: - // microsoftAccountFlags: - // activeDirectoryAppId: - // activeDirectoryScopes: - // activeDirectoryFlags: + // redirectURL: + // flags:@{@"NoThumbnails" : @(YES)}]; return YES; } diff --git a/Examples/iOSExplorer/iOSExplorer/ODXItemCollectionViewController.m b/Examples/iOSExplorer/iOSExplorer/ODXItemCollectionViewController.m index 09226fe..d7c4263 100644 --- a/Examples/iOSExplorer/iOSExplorer/ODXItemCollectionViewController.m +++ b/Examples/iOSExplorer/iOSExplorer/ODXItemCollectionViewController.m @@ -87,7 +87,9 @@ - (void)signInAction if (!error){ self.client = client; [self loadChildren]; - self.navigationItem.rightBarButtonItem = self.actions; + dispatch_async(dispatch_get_main_queue(), ^(){ + self.navigationItem.rightBarButtonItem = self.actions; + }); } else{ [self showErrorAlert:error]; @@ -105,12 +107,12 @@ - (void)signOutAction self.client = nil; self.currentItem = nil; self.title = @"OneDrive"; - self.navigationItem.hidesBackButton = YES; dispatch_async(dispatch_get_main_queue(), ^(){ + self.navigationItem.hidesBackButton = YES; + self.navigationItem.rightBarButtonItem = self.signIn; // Reload from main thread [self.collectionView reloadData]; }); - self.navigationItem.rightBarButtonItem = self.signIn; }]; } diff --git a/OneDriveSDK.podspec b/OneDriveSDK.podspec index b8e84c3..bd6b939 100644 --- a/OneDriveSDK.podspec +++ b/OneDriveSDK.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| s.name = "OneDriveSDK" - s.version = "1.0.5" + s.version = "1.1.0" s.summary = "OneDrive iOS SDK" s.description = <<-DESC diff --git a/OneDriveSDK/Accounts/ODAADServiceInfo.h b/OneDriveSDK/Accounts/ODAADServiceInfo.h index 9062152..fd7e820 100644 --- a/OneDriveSDK/Accounts/ODAADServiceInfo.h +++ b/OneDriveSDK/Accounts/ODAADServiceInfo.h @@ -24,6 +24,10 @@ @interface ODAADServiceInfo : ODServiceInfo -- (instancetype)initWithClientId:(NSString *)clientId scopes:(NSArray *)scopes redirectURL:(NSString *)redirectURL flags:(NSDictionary *)flags; +- (instancetype)initWithClientId:(NSString *)clientId + capability:(NSString *)capability + resourceId:(NSString *)resourceId + redirectURL:(NSString *)redirectURL + flags:(NSDictionary *)flags; @end diff --git a/OneDriveSDK/Accounts/ODAADServiceInfo.m b/OneDriveSDK/Accounts/ODAADServiceInfo.m index ec56aeb..82a7fbb 100644 --- a/OneDriveSDK/Accounts/ODAADServiceInfo.m +++ b/OneDriveSDK/Accounts/ODAADServiceInfo.m @@ -23,28 +23,50 @@ #import "ODServiceInfo+Protected.h" #import "ODAADServiceInfo.h" #import "ODBusinessAuthProvider.h" +#import "ODAuthConstants.h" @implementation ODAADServiceInfo +- (instancetype) initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self){ + //Migrate ApiEndpoint + if (!_apiEndpoint){ + //old versions of the SDK only supported /_api/v2.0/me attached to resourceId + _apiEndpoint = [_resourceId stringByAppendingPathComponent:[OD_ACTIVE_DIRECTORY_URL_SUFFIX copy]]; + } + } + return self; +} -- (instancetype)initWithClientId:(NSString *)clientId scopes:(NSArray *)scopes redirectURL:(NSString *)redirectURL flags:(NSDictionary *)flags +- (instancetype)initWithClientId:(NSString *)clientId + capability:(NSString *)capability + resourceId:(NSString *)resourceId + redirectURL:(NSString *)redirectURL + flags:(NSDictionary *)flags { NSParameterAssert(redirectURL); - self = [super initWithClientId:clientId scopes:scopes flags:flags]; + + self = [super initWithClientId:clientId scopes:nil flags:flags]; if (self){ + _capability = capability; _redirectURL = redirectURL; + _resourceId = resourceId; + _authorityURL = [OD_ACTIVE_DIRECTORY_AUTH_URL copy]; + _discoveryServiceURL = [OD_DISCOVERY_SERVICE_URL copy]; } return self; } -- (NSString *)apiEndpoint +- (id )createAuthProviderWithSession:(id )session accountStore:(id )accountStore logger:(id )logger { - return [self.resourceId stringByAppendingPathComponent:@"_api/v2.0/me/"]; + return [[ODBusinessAuthProvider alloc] initWithServiceInfo:self httpProvider:session accountStore:accountStore logger:logger]; } -- (id )createAuthProviderWithSession:(id )session accountStore:(id )accountStore logger:(id )logger +- (ODAccountType)accountType { - return [[ODBusinessAuthProvider alloc] initWithServiceInfo:self httpProvider:session accountStore:accountStore logger:logger]; + return ODADAccount; } @end diff --git a/OneDriveSDK/Accounts/ODAppConfiguration.h b/OneDriveSDK/Accounts/ODAppConfiguration.h index b9687f2..dfe15c8 100644 --- a/OneDriveSDK/Accounts/ODAppConfiguration.h +++ b/OneDriveSDK/Accounts/ODAppConfiguration.h @@ -32,19 +32,19 @@ /** Configuration for the application. All app information should match the information in your app portal with Microsoft Accounts or Azure Active Directory. - Visit https://dev.onedrive.com/README.htm for more information. + @see https://dev.onedrive.com/README.htm for more information. */ @interface ODAppConfiguration : NSObject /** Application Id for OneDrive registered with Microsoft Account. - See https://dev.onedrive.com/auth/msa_oauth.htm for registration information. + @see https://dev.onedrive.com/auth/msa_oauth.htm for registration information. */ @property (strong, nonatomic) NSString *microsoftAccountAppId; /** Scopes to be used for OneDrive registered with Microsoft Account. - See https://dev.onedrive.com/auth/msa_oauth.htm for registration information. + @see https://dev.onedrive.com/auth/msa_oauth.htm for registration information. */ @property (strong, nonatomic) NSArray *microsoftAccountScopes; @@ -53,60 +53,78 @@ */ @property (strong, nonatomic) NSDictionary *microsoftAccountFlags; +/** + The API Endpoint for the Micrsoft Account Service (defaults to onedrive) + */ +@property (strong, nonatomic) NSString *microsoftAccountApiEndpoint; + /** Application Id for OneDrive for Business. - See https://dev.onedrive.com/auth/aad_oauth.htm for registration information. + @see https://dev.onedrive.com/auth/aad_oauth.htm for registration information. */ @property (strong, nonatomic) NSString *activeDirectoryAppId; /** Redirect URL for OneDrive for Business. - See https://dev.onedrive.com/auth/aad_oauth.htm for registration information. - Warning: This value must be the same as the RedirectURL provided in the Azure Active Directory portal. + @see https://dev.onedrive.com/auth/aad_oauth.htm for registration information. + @warning This value must be the same as the RedirectURL provided in the Azure Active Directory portal. */ @property (strong, nonatomic) NSString *activeDirectoryRedirectURL; /** - Scopes to be used for OneDrive for Business. - See https://dev.onedrive.com/auth/aad_oauth.htm for registration information. + Capability for Active Directory defaults to MyFiles + @see https://dev.onedrive.com/auth/aad_oauth.htm for registration information. + @warning may be nil. + */ +@property (strong, nonatomic) NSString *activeDirectoryCapability; + +/** + The resourceId you wish to access. + @warning may be nil. + */ +@property (strong, nonatomic) NSString *activeDirectoryResourceId; + +/** + The API Endpoint URL for Active Driectory. + @warning may be nil. */ -@property (strong, nonatomic) NSArray *activeDirectoryScopes; +@property (strong, nonatomic) NSString *activeDirectoryApiEndpointURL; /** Any flags to be passed into the ODClient if the client is a OneDrive for Business account. - See [ODClient serviceFlags]. + @see [ODClient serviceFlags]. */ @property (strong, nonatomic) NSDictionary *activeDirectoryFlags; /** The parent view controller to present the Authentication View controller on top of. - Warning: If no ParentAuthController is provided, the default will be the root view controller of the application. + @warning If no ParentAuthController is provided, the default will be the root view controller of the application. */ @property (strong, nonatomic) UIViewController *parentAuthController; /** The Service Info Provider to be used to discover the correct authentication service. - Warning: If this is nil you must provide an authentication provider. + @warning If this is nil you must provide an authentication provider. See authProvider. */ @property (strong, nonatomic) ODServiceInfoProvider *serviceInfoProvider; /** The httpProvider to be used for all network requests. - Warning: This must not be nil. + @warning This must not be nil. */ @property (strong, nonatomic) id httpProvider; /** The accountStore to be used for persistent access to the service. - Warning: If this is nil there will be no storage of accounts. Users will have to sign in every time they re-open the application. + @warning If this is nil there will be no storage of accounts. Users will have to sign in every time they re-open the application. */ @property (strong, nonatomic) id accountStore; /** The Authentication Provider to be used. - Warning: This may be nil, and if it is, there must be an ODServiceInfoProvider to discover the correct authentication provider to use. - See serviceInfoProvider. + @warning This may be nil, and if it is, there must be an ODServiceInfoProvider to discover the correct authentication provider to use. + @see serviceInfoProvider. */ @property (strong, nonatomic) id authProvider; diff --git a/OneDriveSDK/Accounts/ODMSAServiceInfo.h b/OneDriveSDK/Accounts/ODMSAServiceInfo.h index 2f9e588..472b659 100644 --- a/OneDriveSDK/Accounts/ODMSAServiceInfo.h +++ b/OneDriveSDK/Accounts/ODMSAServiceInfo.h @@ -24,6 +24,8 @@ @interface ODMSAServiceInfo : ODServiceInfo -- (instancetype)initWithClientId:(NSString *)clientId scopes:(NSArray *)scopes flags:(NSDictionary *)flags; - +- (instancetype)initWithClientId:(NSString *)clientId + scopes:(NSArray *)scopes + flags:(NSDictionary *)flags + apiEndpoint:(NSString *)apiEndpoint; @end diff --git a/OneDriveSDK/Accounts/ODMSAServiceInfo.m b/OneDriveSDK/Accounts/ODMSAServiceInfo.m index 7337b99..e7a2ebc 100644 --- a/OneDriveSDK/Accounts/ODMSAServiceInfo.m +++ b/OneDriveSDK/Accounts/ODMSAServiceInfo.m @@ -26,22 +26,34 @@ @implementation ODMSAServiceInfo -- (instancetype)initWithClientId:(NSString *)clientId scopes:(NSArray *)scopes flags:(NSDictionary *)flags +- (instancetype)initWithClientId:(NSString *)clientId + scopes:(NSArray *)scopes + flags:(NSDictionary *)flags + apiEndpoint:(NSString *)apiEndpoint; { NSParameterAssert(scopes); self = [super initWithClientId:clientId scopes:scopes flags:flags]; if (self){ - _resourceId = [OD_microsoftAccounnt_ENDPOINT copy]; - _redirectURL = [MSARedirectURL copy]; - _logoutURL = [MSALogOutURL copy]; + _authorityURL = [OD_MICROSOFT_ACCOUNT_AUTH_URL copy]; + _tokenURL = [OD_MICROSOFT_ACCOUNT_TOKEN_URL copy]; + _apiEndpoint = apiEndpoint; + _redirectURL = [OD_MICROSOFT_ACCOUNT_REDIRECT_URL copy]; + _logoutURL = [OD_MICROSOFT_ACCOUNT_LOGOUT_URL copy]; } return self; } -- (NSString *)apiEndpoint +- (instancetype)initWithCoder:(NSCoder *)aDecoder { - return self.resourceId; + self = [super initWithCoder:aDecoder]; + if (self){ + //Migrate the APIEndpoint from resource Id if this was loaded from an older SDK version + if (!_apiEndpoint){ + _apiEndpoint = _resourceId; + } + } + return self; } - (NSDictionary *)authRequestParameters @@ -56,4 +68,9 @@ - (NSDictionary *)authRequestParameters return [[ODPersonalAuthProvider alloc] initWithServiceInfo:self httpProvider:session accountStore:accountStore logger:logger]; } +- (ODAccountType)accountType +{ + return ODMSAAccount; +} + @end diff --git a/OneDriveSDK/Accounts/ODServiceInfo+Protected.h b/OneDriveSDK/Accounts/ODServiceInfo+Protected.h index a66f0bb..617c783 100644 --- a/OneDriveSDK/Accounts/ODServiceInfo+Protected.h +++ b/OneDriveSDK/Accounts/ODServiceInfo+Protected.h @@ -35,10 +35,10 @@ NSString *_discoveryServiceURL; NSString *_userEmail; NSString *_apiEndpoint; + NSString *_capability; NSArray *_scopes; } - - (instancetype)initWithClientId:(NSString *)clientId scopes:(NSArray *)scopes flags:(NSDictionary *)flags; - (NSDictionary *)authRequestParameters; diff --git a/OneDriveSDK/Accounts/ODServiceInfoProvider.h b/OneDriveSDK/Accounts/ODServiceInfoProvider.h index fe4b665..cb59ce6 100644 --- a/OneDriveSDK/Accounts/ODServiceInfoProvider.h +++ b/OneDriveSDK/Accounts/ODServiceInfoProvider.h @@ -42,4 +42,5 @@ typedef void(^disambiguationCompletion)(UIViewController *presentedDiscoveryCont - (void)getServiceInfoWithViewController:(UIViewController *)viewController appConfiguration:(ODAppConfiguration *)appConfig completion:(disambiguationCompletion)completionHandler; + @end diff --git a/OneDriveSDK/Accounts/ODServiceInfoProvider.m b/OneDriveSDK/Accounts/ODServiceInfoProvider.m index d4be786..a5e4f51 100644 --- a/OneDriveSDK/Accounts/ODServiceInfoProvider.m +++ b/OneDriveSDK/Accounts/ODServiceInfoProvider.m @@ -48,57 +48,64 @@ - (void)getServiceInfoWithViewController:(UIViewController *)viewController self.appConfig = appConfig; self.completionHandler = completionHandler; - NSURL *endURL = [NSURL URLWithString:@"https://localhost:777"]; - NSURL *startURL =[NSURL URLWithString:@"https://api.office.com/discovery/v2.0/me/FirstSignIn?redirect_uri=https://localhost:777&scope=MyFiles"]; + if (appConfig.microsoftAccountAppId && appConfig.activeDirectoryAppId){ + [self discoverServiceInfoWithViewController:viewController]; + } + // If we only have a one AppId there is no need to display the disambiguation page we can only select an MSA service info + else if(appConfig.microsoftAccountAppId){ + ODServiceInfo *serviceInfo = [self serviceInfoWithType:ODMSAAccount appConfig:self.appConfig]; + self.completionHandler(viewController, serviceInfo, nil); + } + else if(appConfig.activeDirectoryAppId){ + ODServiceInfo *serviceInfo = [self serviceInfoWithType:ODADAccount appConfig:self.appConfig]; + self.completionHandler(viewController, serviceInfo, nil); + } + +} + +- (void)discoverServiceInfoWithViewController:(UIViewController *)viewController +{ + NSURL *endURL = [NSURL URLWithString:OD_DISCOVERY_REDIRECT_URL]; + NSURL *startURL =[NSURL URLWithString:[NSString stringWithFormat:@"%@&ru=%@", OD_DISAMBIGUATION_URL, OD_DISCOVERY_REDIRECT_URL]]; [self.appConfig.logger logWithLevel:ODLogDebug message:@"ServiceInfo provider starting discovery service with URL:", startURL]; __block ODAuthenticationViewController *discoveryViewController = [[ODAuthenticationViewController alloc] initWithStartURL:startURL - endURL:endURL - success:^(NSURL *endURL, NSError *error){ - if (!error){ - [self.appConfig.logger logWithLevel:ODLogDebug message:@"discovered account from response : %@", endURL]; - ODServiceInfo *serviceInfo = [self serviceInfoFromDiscoveryResponse:endURL appConfig:self.appConfig error:&error]; - if (error){ - [self.appConfig.logger logWithLevel:ODLogError message:@"Error parsing authentication service response %@", error]; - } - self.completionHandler(discoveryViewController, serviceInfo, error); - } - else { - self.completionHandler(discoveryViewController, nil, error); - } - + endURL:endURL + success:^(NSURL *endURL, NSError *error){ + if (!error){ + [self.appConfig.logger logWithLevel:ODLogDebug message:@"discovered account from response : %@", endURL]; + ODServiceInfo *serviceInfo = [self serviceInfoFromDiscoveryResponse:endURL appConfig:self.appConfig error:&error]; + if (error){ + [self.appConfig.logger logWithLevel:ODLogError message:@"Error parsing authentication service response %@", error]; + } + self.completionHandler(discoveryViewController, serviceInfo, error); + } + else { + self.completionHandler(discoveryViewController, nil, error); + } }]; - dispatch_async(dispatch_get_main_queue(), ^(){ - UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:discoveryViewController]; - navController.modalPresentationStyle = viewController.modalPresentationStyle; - UIViewController *viewControllerToPresentOn = viewController; - while (viewControllerToPresentOn.presentedViewController) { - viewControllerToPresentOn = viewControllerToPresentOn.presentedViewController; - } - [viewControllerToPresentOn presentViewController:navController animated:YES completion:^{ - [discoveryViewController loadInitialRequest]; - }]; + dispatch_async(dispatch_get_main_queue(), ^(){ + UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:discoveryViewController]; + navController.modalPresentationStyle = viewController.modalPresentationStyle; + UIViewController *viewControllerToPresentOn = viewController; + while (viewControllerToPresentOn.presentedViewController) { + viewControllerToPresentOn = viewControllerToPresentOn.presentedViewController; + } + [viewControllerToPresentOn presentViewController:navController animated:YES completion:^{ + [discoveryViewController loadInitialRequest]; + }]; }); - } - (ODServiceInfo *)serviceInfoFromDiscoveryResponse:(NSURL *)url appConfig:(ODAppConfiguration *)appConfig error:(NSError * __autoreleasing *)error { NSDictionary *queryParams = [ODAuthHelper decodeQueryParameters:url]; - NSString *authRequestString = queryParams[OD_DISCOVERY_AUTH_SERVICE]; - NSString *tokenService = queryParams[OD_DISCOVERY_TOKEN_SERVICE]; - NSString *discoverResource = queryParams[OD_DISCOVERY_RESROUCE]; - NSString *discoveryService = queryParams[OD_DISCOVERY_SERVICE]; - NSInteger accountType = [queryParams[OD_DISCOVERY_ACCOUNT_TYPE] integerValue]; + NSString *accountType = queryParams[OD_DISCOVERY_ACCOUNT_TYPE]; NSString *userEmail = queryParams[OD_AUTH_USER_EMAIL]; - ODServiceInfo *serviceInfo = [self serviceInfoWithType:accountType appConfig:appConfig]; + ODServiceInfo *serviceInfo = [self serviceInfoWithString:accountType appConfig:appConfig]; if (serviceInfo){ serviceInfo.userEmail = userEmail; - serviceInfo.authorityURL = authRequestString; - serviceInfo.tokenURL = tokenService; - serviceInfo.resourceId = ([discoverResource isEqualToString:@""]) ? serviceInfo.resourceId : discoverResource ; - serviceInfo.discoveryServiceURL = [NSString stringWithFormat:@"%@/services", discoveryService]; } else { if (error){ @@ -108,14 +115,39 @@ - (ODServiceInfo *)serviceInfoFromDiscoveryResponse:(NSURL *)url appConfig:(ODAp return serviceInfo; } +- (ODServiceInfo *)serviceInfoWithString:(NSString *)accountType appConfig:(ODAppConfiguration *)appConfig +{ + return [self serviceInfoWithType:[self accountTypeFromString:accountType] appConfig:appConfig]; +} + +- (ODAccountType)accountTypeFromString:(NSString *)accountType +{ + ODAccountType type = ODUnknownAccount; + if (accountType){ + if ([accountType isEqualToString:OD_DISCOVERY_ACCOUNT_TYPE_MSA]){ + type = ODMSAAccount; + } + else if ( [accountType isEqualToString:OD_DISCOVERY_ACCOUNT_TYPE_AAD]){ + type = ODADAccount; + } + } + return type; +} + - (ODServiceInfo *)serviceInfoWithType:(ODAccountType)type appConfig:(ODAppConfiguration *)appConfig { ODServiceInfo *serviceInfo = nil; switch (type) { case ODADAccount: if (appConfig.activeDirectoryAppId){ + NSString *resourceId = appConfig.activeDirectoryResourceId; + // If we don't know the resourceId we must discover it using the discovery service + if (!resourceId){ + resourceId = OD_DISCOVERY_SERVICE_RESOURCEID; + } serviceInfo = [[ODAADServiceInfo alloc] initWithClientId:appConfig.activeDirectoryAppId - scopes:appConfig.activeDirectoryScopes + capability:appConfig.activeDirectoryCapability + resourceId:resourceId redirectURL:appConfig.activeDirectoryRedirectURL flags:appConfig.activeDirectoryFlags]; } @@ -124,9 +156,12 @@ - (ODServiceInfo *)serviceInfoWithType:(ODAccountType)type appConfig:(ODAppConfi if (appConfig.microsoftAccountAppId){ serviceInfo = [[ODMSAServiceInfo alloc] initWithClientId:appConfig.microsoftAccountAppId scopes:appConfig.microsoftAccountScopes - flags:appConfig.microsoftAccountFlags]; + flags:appConfig.microsoftAccountFlags + apiEndpoint:appConfig.microsoftAccountApiEndpoint]; } break; + case ODUnknownAccount: + default : break; } return serviceInfo; } diff --git a/OneDriveSDK/Auth/ODAuthProvider+Protected.h b/OneDriveSDK/Auth/ODAuthProvider+Protected.h index da946d1..95746a4 100644 --- a/OneDriveSDK/Auth/ODAuthProvider+Protected.h +++ b/OneDriveSDK/Auth/ODAuthProvider+Protected.h @@ -32,6 +32,11 @@ @property ODServiceInfo *serviceInfo; +/** + The proper telemtryHeaderField for the given service. + */ +@property (readonly) NSString *telemtryHeaderField; + /** Creates an error from a URL returned by an authentication service. @param url The URL returned by the service. @@ -83,6 +88,8 @@ */ - (NSURLRequest *)logoutRequest; + + @end #endif diff --git a/OneDriveSDK/Auth/ODBaseAuthProvider.m b/OneDriveSDK/Auth/ODBaseAuthProvider.m index bcb8b90..72d727b 100644 --- a/OneDriveSDK/Auth/ODBaseAuthProvider.m +++ b/OneDriveSDK/Auth/ODBaseAuthProvider.m @@ -148,6 +148,8 @@ - (void)appendAuthHeaders:(NSMutableURLRequest *)request completion:(void (^)(NS NSParameterAssert(completionHandler); NSParameterAssert(request); + NSString *telemtryValue = [NSString stringWithFormat:OD_TELEMTRY_HEADER_VALUE_FORMAT, OD_SDK_VERSION]; + [request setValue:telemtryValue forHTTPHeaderField:self.telemtryHeaderField]; if([ODAuthHelper shouldRefreshSession:self.accountSession]){ [self.logger logWithLevel:ODLogDebug message:@"Refreshing session %@", self.accountSession.accountId]; [self refreshAndStoreAccountSession:self.accountSession withCompletion:^(NSError *error){ @@ -217,7 +219,6 @@ - (void)getTokenWithCode:(NSString *)code completion:(AuthCompletion)completion }] resume]; } - - (NSError *)errorFromURL:(NSURL *)url { NSAssert(NO, @"Must Implement in base class"); diff --git a/OneDriveSDK/Auth/ODBusinessAuthProvider.m b/OneDriveSDK/Auth/ODBusinessAuthProvider.m index 7ec0571..46c86ec 100644 --- a/OneDriveSDK/Auth/ODBusinessAuthProvider.m +++ b/OneDriveSDK/Auth/ODBusinessAuthProvider.m @@ -63,15 +63,16 @@ - (void) authenticateWithViewController:(UIViewController*)viewController comple // If the resourceId being used is for the discovery service if ([self.serviceInfo.discoveryServiceURL containsString:self.serviceInfo.resourceId]){ // Find the resourceIds needed - [self discoverResourceWithAuthResult:result completion:^(NSString *resourceIds, NSError *error){ + [self discoverResourceWithAuthResult:result completion:^(ODServiceInfo *serviceInfo, NSError *error){ //Refresh the token with the correct resource Ids + if (!error){ + self.serviceInfo = serviceInfo; + } if (result.tokenCacheStoreItem.refreshToken){ - [self.authContext acquireTokenByRefreshToken:result.tokenCacheStoreItem.refreshToken clientId:self.serviceInfo.appId resource:resourceIds completionBlock:^(ADAuthenticationResult *innerResult){ + [self.authContext acquireTokenByRefreshToken:result.tokenCacheStoreItem.refreshToken clientId:self.serviceInfo.appId resource:self.serviceInfo.resourceId completionBlock:^(ADAuthenticationResult *innerResult){ if (innerResult.status == AD_SUCCEEDED) { innerResult.tokenCacheStoreItem.userInformation = result.tokenCacheStoreItem.userInformation; - // the refresh response doesn't contain the user information so we must set it from the previous response - self.serviceInfo.resourceId = resourceIds; [self setAccountSessionWithAuthResult:innerResult]; completionHandler(nil); } @@ -109,19 +110,17 @@ - (void)setAccountSessionWithAuthResult:(ADAuthenticationResult *)result } } --(void)discoverResourceWithAuthResult:(ADAuthenticationResult *)result completion:(void (^)(NSString *, NSError *))completion +-(void)discoverResourceWithAuthResult:(ADAuthenticationResult *)result completion:(void (^)(ODServiceInfo *, NSError *))completion { NSMutableURLRequest *discoveryRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.serviceInfo.discoveryServiceURL]]; [ODAuthHelper appendAuthHeaders:discoveryRequest token:result.accessToken]; [[self.httpProvider dataTaskWithRequest:discoveryRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ if (!error){ NSDictionary *responseObject = [ODAuthHelper sessionDictionaryWithResponse:response data:data error:&error]; - NSString *resourceIds = nil; if (responseObject){ - NSSet *capabilitySet = [self capabilitySetWithScopes:self.serviceInfo.scopes]; - resourceIds = [self resourceIdsWithCapabilities:capabilitySet discoveryResponse:responseObject]; + [self setServiceInfo:self.serviceInfo withCapability:self.serviceInfo.capability discoveryResponse:responseObject]; } - completion(resourceIds, error); + completion(self.serviceInfo, error); } else{ completion(nil, error); @@ -129,38 +128,15 @@ -(void)discoverResourceWithAuthResult:(ADAuthenticationResult *)result completio }] resume]; } -- (NSString *)resourceIdsWithCapabilities:(NSSet *)capabilities discoveryResponse:(NSDictionary *)discoveryResponse +- (void)setServiceInfo:(ODServiceInfo *)serviceInfo withCapability:(NSString *)capability discoveryResponse:(NSDictionary *)discoveryResponse { - __block NSMutableArray *resourceIds = [NSMutableArray array]; NSArray *values = discoveryResponse[@"value"]; [values enumerateObjectsUsingBlock:^(NSDictionary *serviceResponse, NSUInteger index, BOOL *stop){ - if ([capabilities containsObject:serviceResponse[@"capability"]]){ - NSString *serviceResourceId = serviceResponse[@"serviceResourceId"]; - if (![resourceIds containsObject:serviceResourceId]){ - [resourceIds addObject:serviceResourceId]; - } - } - }]; - return [resourceIds componentsJoinedByString:@" "]; -} - -- (NSSet *)capabilitySetWithScopes:(NSArray *)scopes -{ - __block NSMutableSet *scopesSet = [NSMutableSet set]; - [self.serviceInfo.scopes enumerateObjectsUsingBlock:^(NSString *scope, NSUInteger index, BOOL *stop){ - // trim off the end part of the scopes if it exists - // i.e. if the scope is MyFiles.readwrite we just want MyFiles - NSRange prefixRange = [scope rangeOfString:@"."]; - NSString *capability = nil; - if (prefixRange.location){ - capability = [scope substringToIndex:prefixRange.location]; - } - else { - capability = scope; + if ([serviceResponse[@"capability"] isEqualToString:capability]){ + serviceInfo.resourceId = serviceResponse[@"serviceResourceId"]; + serviceInfo.apiEndpoint = serviceResponse[@"serviceEndpointUri"]; } - [scopesSet addObject:capability]; }]; - return scopesSet; } - (void)refreshSession:(ODAccountSession *)session withCompletion:(void (^)(ODAccountSession *updatedSession, NSError *error))completionHandler @@ -181,6 +157,11 @@ - (void)refreshSession:(ODAccountSession *)session withCompletion:(void (^)(ODAc }]; } +- (NSString*)telemtryHeaderField +{ + return [OD_AAD_TELEMTRY_HEADER copy]; +} + - (ADAuthenticationContext *)authContext { if (!_authContext){ diff --git a/OneDriveSDK/Auth/ODPersonalAuthProvider.m b/OneDriveSDK/Auth/ODPersonalAuthProvider.m index 1038be2..7690d30 100644 --- a/OneDriveSDK/Auth/ODPersonalAuthProvider.m +++ b/OneDriveSDK/Auth/ODPersonalAuthProvider.m @@ -85,9 +85,9 @@ - (NSURLRequest *)tokenRequestWithParameters:(NSDictionary *)params { return [ODAuthHelper requestWithMethod:@"POST" - URL:[NSURL URLWithString:self.serviceInfo.tokenURL] - parameters:params - headers:@{OD_API_HEADER_CONTENTTYPE :OD_API_HEADER_CONTENTTYPE_FORMENCODED}]; + URL:[NSURL URLWithString:self.serviceInfo.tokenURL] + parameters:params + headers:@{OD_API_HEADER_CONTENTTYPE :OD_API_HEADER_CONTENTTYPE_FORMENCODED}]; } @@ -116,4 +116,10 @@ - (NSURLRequest *)logoutRequest } return request; } + +- (NSString *)telemtryHeaderField +{ + return [OD_MSA_TELEMTRY_HEADER copy]; +} + @end diff --git a/OneDriveSDK/Common/ODAuthConstants.h b/OneDriveSDK/Common/ODAuthConstants.h index 0260c7d..1f25b3c 100644 --- a/OneDriveSDK/Common/ODAuthConstants.h +++ b/OneDriveSDK/Common/ODAuthConstants.h @@ -23,6 +23,7 @@ #define OneDriveSDK_ODAuthConstants_h typedef NS_ENUM(NSInteger, ODAccountType){ + ODUnknownAccount = 0, ODMSAAccount = 1, ODADAccount = 2, }; @@ -44,6 +45,8 @@ typedef NS_ENUM(NSInteger, ODAuthErrorType) { ODInvalidAccountType }; +extern NSString * const OD_SDK_VERSION; + extern NSString * const OD_AUTH_ERROR_DOMAIN; extern NSString * const OD_AUTH_ERROR_KEY; @@ -70,20 +73,32 @@ extern NSString * const OD_AUTH_TOKEN_ID; extern NSString * const OD_AUTH_USER_NAME; extern NSString * const OD_AUTH_USER_EMAIL; +extern NSString * const OD_MSA_TELEMTRY_HEADER; +extern NSString * const OD_AAD_TELEMTRY_HEADER; +extern NSString * const OD_TELEMTRY_HEADER_VALUE_FORMAT; -extern NSString * const OD_DISCOVERY_AUTH_SERVICE; -extern NSString * const OD_DISCOVERY_TOKEN_SERVICE; -extern NSString * const OD_DISCOVERY_RESROUCE; -extern NSString * const OD_DISCOVERY_SERVICE; extern NSString * const OD_DISCOVERY_ACCOUNT_TYPE; +extern NSString * const OD_DISCOVERY_ACCOUNT_TYPE_AAD; +extern NSString * const OD_DISCOVERY_ACCOUNT_TYPE_MSA; +extern NSString * const OD_DISCOVERY_SERVICE_RESOURCEID; +extern NSString * const OD_DISCOVERY_SERVICE_URL; +extern NSString * const OD_DISAMBIGUATION_URL; + +extern NSString * const OD_MICROSOFT_ACCOUNT_ENDPOINT_HOST; +extern NSString * const OD_MICROSOFT_ACCOUNT_AUTH_URL; +extern NSString * const OD_MICROSOFT_ACCOUNT_TOKEN_URL; +extern NSString * const OD_MICROSOFT_ACCOUNT_REDIRECT_URL; +extern NSString * const OD_MICROSOFT_ACCOUNT_LOGOUT_URL; +extern NSString * const OD_MICROSOFT_ACCOUNT_API_VERSION; +extern NSString * const OD_MICROSOFT_ACCOUNT_ENDPOINT; + +extern NSString * const OD_DISCOVERY_REDIRECT_URL; +extern NSString * const OD_MICROSOFT_ACCOUNT_ENDPOINT; -extern NSString * const ODLocalRedirectURL; -extern NSString * const MSAEndpointHost; -extern NSString * const MSAAuthURL; -extern NSString * const MSATokenURL; -extern NSString * const MSARedirectURL; -extern NSString * const MSALogOutURL; +extern NSString * const OD_ACTIVE_DIRECTORY_AUTH_URL; +extern NSString * const OD_ACTIVE_DIRECTORY_AUTH_ENDPOINT_HOST; +extern NSString * const OD_ACTIVE_DIRECTORY_URL_SUFFIX; -extern NSString * const OD_microsoftAccounnt_ENDPOINT; +extern NSString * const OD_MICROSOFT_ACCOUNT_API_VERSION; #endif diff --git a/OneDriveSDK/Common/ODAuthConstants.m b/OneDriveSDK/Common/ODAuthConstants.m index db44fa2..1e0dea3 100644 --- a/OneDriveSDK/Common/ODAuthConstants.m +++ b/OneDriveSDK/Common/ODAuthConstants.m @@ -22,6 +22,8 @@ #import #import "ODAuthConstants.h" +NSString * const OD_SDK_VERSION = @"1.1.0"; + NSString * const OD_AUTH_ERROR_DOMAIN = @"com.microsoft.onedrivesdk.autherror"; NSString * const OD_AUTH_ERROR_KEY = @"ODAuthErrorKey"; @@ -31,6 +33,11 @@ NSString * const OD_API_HEADER_APPLICATION_JSON = @"application/json"; NSString * const OD_API_HEADER_ACCEPT = @"accept"; +NSString * const OD_MSA_TELEMTRY_HEADER = @"X-RequestStats"; +NSString * const OD_AAD_TELEMTRY_HEADER = @"X-ClientService-ClientTag"; + +NSString * const OD_TELEMTRY_HEADER_VALUE_FORMAT = @"SDK-Version=iOS-v%@"; + NSString * const OD_AUTH_ACCESS_TOKEN = @"access_token"; NSString * const OD_AUTH_CODE = @"code"; NSString * const OD_AUTH_CLIENTID = @"client_id"; @@ -48,17 +55,25 @@ NSString * const OD_AUTH_USER_NAME = @"username"; NSString * const OD_AUTH_USER_EMAIL = @"user_email"; -NSString * const OD_DISCOVERY_AUTH_SERVICE = @"authorization_service"; -NSString * const OD_DISCOVERY_TOKEN_SERVICE = @"token_service"; -NSString * const OD_DISCOVERY_RESROUCE = @"discovery_resource"; -NSString * const OD_DISCOVERY_SERVICE = @"discovery_service"; + + NSString * const OD_DISCOVERY_ACCOUNT_TYPE = @"account_type"; +NSString * const OD_DISCOVERY_ACCOUNT_TYPE_AAD = @"AAD"; +NSString * const OD_DISCOVERY_ACCOUNT_TYPE_MSA = @"MSA"; +NSString * const OD_DISCOVERY_SERVICE_RESOURCEID = @"https://api.office.com/discovery/"; +NSString * const OD_DISCOVERY_SERVICE_URL = @"https://api.office.com/discovery/v2.0/me/services"; +NSString * const OD_DISAMBIGUATION_URL = @"https://onedrive.live.com/picker/accountchooser?load_login=false"; + +NSString * const OD_MICROSOFT_ACCOUNT_ENDPOINT_HOST = @"login.live.com"; +NSString * const OD_MICROSOFT_ACCOUNT_AUTH_URL = @"https://login.live.com/oauth20_authorize.srf"; +NSString * const OD_MICROSOFT_ACCOUNT_TOKEN_URL = @"https://login.live.com/oauth20_token.srf"; +NSString * const OD_MICROSOFT_ACCOUNT_REDIRECT_URL = @"https://login.live.com/oauth20_desktop.srf"; +NSString * const OD_MICROSOFT_ACCOUNT_LOGOUT_URL = @"https://login.live.com/oauth20_logout.srf"; +NSString * const OD_DISCOVERY_REDIRECT_URL = @"https://localhost:5000"; -NSString * const MSAEndpointHost = @"login.live.com"; -NSString * const MSAAuthURL = @"https://login.live.com/oauth20_authorize.srf"; -NSString * const MSATokenURL = @"https://login.live.com/oauth20_token.srf"; -NSString * const MSARedirectURL = @"https://login.live.com/oauth20_desktop.srf"; -NSString * const ODLocalRedirectURL = @"https://localhost:5000"; -NSString * const MSALogOutURL = @"https://login.live.com/oauth20_logout.srf"; +NSString * const OD_MICROSOFT_ACCOUNT_ENDPOINT = @"https://api.onedrive.com"; +NSString * const OD_MICROSOFT_ACCOUNT_API_VERSION = @"v1.0"; -NSString * const OD_microsoftAccounnt_ENDPOINT = @"https://api.onedrive.com/v1.0"; \ No newline at end of file +NSString * const OD_ACTIVE_DIRECTORY_AUTH_URL = @"https://login.microsoftonline.com/common/oauth2/token"; +NSString * const OD_ACTIVE_DIRECTORY_AUTH_ENDPOINT_HOST = @"login.microsoftoneline.com"; +NSString * const OD_ACTIVE_DIRECTORY_URL_SUFFIX = @"_api/v2.0/me"; \ No newline at end of file diff --git a/OneDriveSDK/Common/ODServiceInfo.h b/OneDriveSDK/Common/ODServiceInfo.h index 5fa0f1c..0bb7fb6 100644 --- a/OneDriveSDK/Common/ODServiceInfo.h +++ b/OneDriveSDK/Common/ODServiceInfo.h @@ -25,6 +25,7 @@ #import "ODAuthProvider.h" #import "ODAccountStoreProtocol.h" #import "ODLoggerProtocol.h" +#import "ODAuthConstants.h" /** The 'ODServiceInfo' object will provide information for the specific authentication service. @@ -45,17 +46,17 @@ /** The URL to retrieve the token with the code from the authentication service. */ -@property NSString *tokenURL; +@property (readonly) NSString *tokenURL; /** The URL to the authentication authority, this is just the host for authority not the full URL. */ -@property NSString *authorityURL; +@property (readonly) NSString *authorityURL; /** The URL to logout of the session. This may be nil. */ -@property NSString *logoutURL; +@property (readonly) NSString *logoutURL; /** The resourceId of the service being access. @@ -67,7 +68,7 @@ /** The URL to use to discovery the resource id. This may be nil. */ -@property NSString *discoveryServiceURL; +@property (readonly) NSString *discoveryServiceURL; /** The email of the user. This may be nil. @@ -75,30 +76,41 @@ @property NSString *userEmail; /** - The host for the api being accessed. - For Personal OneDrive, the host will be https://api.onedrive.com/v1.0/ + The Api Endpoint + For Personal OneDrive, this will be https://api.onedrive.com/v1.0/ */ @property NSString *apiEndpoint; /** - An array of strings containing the scopes for the authentication service. + An array of strings containing the scopes for the authentication service. This may be nil. */ @property NSArray *scopes; +/** + The Active Directory Capability. This may be nil. + */ +@property NSString *capability; + /** Flags for the given service, these are user defined. This may be nil or an empty dictionary */ @property (readonly) NSDictionary *flags; +/** + The account type for the ServiceInfo. + */ +@property (readonly) ODAccountType accountType; + /** Creates and authentication provider with a given ODHttpProvider and ODAccountStore. @param session The ODHttpProvider to be used for network requests. @param accountStore The accountStore for the auth provider to use. @return ODAuthProvider An authentication provider to be used for correct service, created with the given parameters. */ -- (id )authProviderWithURLSession:(id )session +- (id )authProviderWithURLSession:(id )session accountStore:(id )accountStore logger:(id)logger; + @end diff --git a/OneDriveSDK/Common/ODServiceInfo.m b/OneDriveSDK/Common/ODServiceInfo.m index ab69df4..3b8d480 100644 --- a/OneDriveSDK/Common/ODServiceInfo.m +++ b/OneDriveSDK/Common/ODServiceInfo.m @@ -27,10 +27,6 @@ @interface ODServiceInfo() @property (readonly, nonatomic) id authProvider; -- (id )createAuthProviderWithSession:(id )session - accountStore:(id )accountStore - logger:(id )logger; - @end @implementation ODServiceInfo @@ -59,6 +55,8 @@ - (void)encodeWithCoder:(NSCoder *)aCoder [aCoder encodeObject:self.flags forKey:@"flags"]; [aCoder encodeObject:self.scopes forKey:@"scopes"]; [aCoder encodeObject:self.logoutURL forKey:@"logoutURL"]; + [aCoder encodeObject:self.apiEndpoint forKey:@"apiEndpoint"]; + [aCoder encodeObject:self.capability forKey:@"capability"]; } - (instancetype)initWithCoder:(NSCoder *)aDecoder @@ -74,6 +72,8 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder _flags = [aDecoder decodeObjectForKey:@"flags"]; _scopes = [aDecoder decodeObjectForKey:@"scopes"]; _logoutURL = [aDecoder decodeObjectForKey:@"logoutURL"]; + _capability = [aDecoder decodeObjectForKey:@"capability"]; + _apiEndpoint = [aDecoder decodeObjectForKey:@"apiEndpoint"]; } return self; } diff --git a/OneDriveSDK/Extensions/ODClient+Authentication.m b/OneDriveSDK/Extensions/ODClient+Authentication.m index 7abc915..c26924f 100644 --- a/OneDriveSDK/Extensions/ODClient+Authentication.m +++ b/OneDriveSDK/Extensions/ODClient+Authentication.m @@ -104,9 +104,9 @@ + (ODClient *)clientWithAuthProvider:(id )authProvider } + (ODClient *)clientWithAccountSession:(ODAccountSession *)accountSession - httpProvider:(id )httpProvider - accountStore:(id )accountStore - logger:(id )logger + httpProvider:(id )httpProvider + accountStore:(id )accountStore + logger:(id )logger { NSParameterAssert(accountSession); NSParameterAssert(accountStore); @@ -178,7 +178,7 @@ - (void)authenticateWithAppConfig:(ODAppConfiguration *)appConfig { NSParameterAssert(appConfig); - UIViewController *rootViewController = appConfig.parentAuthController; + __block UIViewController *rootViewController = appConfig.parentAuthController; if (appConfig.authProvider){ [self authenticateWithAuthProvider:appConfig.authProvider httpProvider:appConfig.httpProvider @@ -189,8 +189,8 @@ - (void)authenticateWithAppConfig:(ODAppConfiguration *)appConfig else { // We may not know which authentication service to use we have to discover it [appConfig.serviceInfoProvider getServiceInfoWithViewController:rootViewController - appConfiguration:appConfig - completion:^(UIViewController *presentedViewController, ODServiceInfo *serviceInfo, NSError *error){ + appConfiguration:appConfig + completion:^(UIViewController *presentedViewController, ODServiceInfo *serviceInfo, NSError *error){ if (!error){ id authProvider = [serviceInfo authProviderWithURLSession:appConfig.httpProvider accountStore:appConfig.accountStore @@ -198,11 +198,13 @@ - (void)authenticateWithAppConfig:(ODAppConfiguration *)appConfig [self authenticateWithAuthProvider:authProvider httpProvider:appConfig.httpProvider logger:appConfig.logger - viewController:presentedViewController.parentViewController + viewController:(presentedViewController.parentViewController) ? presentedViewController.parentViewController : rootViewController completion:completion]; } else { - [presentedViewController dismissViewControllerAnimated:YES completion:nil]; + if (presentedViewController){ + [presentedViewController dismissViewControllerAnimated:YES completion:nil]; + } completion(error); } }]; diff --git a/OneDriveSDK/Extensions/ODClient+DefaultConfiguration.h b/OneDriveSDK/Extensions/ODClient+DefaultConfiguration.h index d35e317..0c81a43 100644 --- a/OneDriveSDK/Extensions/ODClient+DefaultConfiguration.h +++ b/OneDriveSDK/Extensions/ODClient+DefaultConfiguration.h @@ -70,36 +70,70 @@ + (void)setMicrosoftAccountAppId:(NSString *)microsoftAccounntAppId scopes:(NSArray *)microsoftAccounntScopes; + + /** - Sets the OneDrive for Business app information. + Calls setActiveDirectoryAppId:capability:redirectURL with OneDrive for business Capability (MyFiles) + @param activeDirectoryAppId The applicaiton id. Must not be nil. + @param redirectURL the redirect url to be used with Azure Active Directory. Most not be nil. + */ ++ (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId + redirectURL:(NSString *)activeDirectoryRedirectURL; + +/** + Calls setActiveDirectoryAppId:capability:resouceId:apiEndpoint:redirectURL:flags: with the given information. + @param activeDirectoryAppId The application id. Must not be nil. + @param redirectURL the direct url to be used with Azure Active Directory. Must not be nil + */ ++ (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId + redirectURL:(NSString *)activeDirectoryRedirectURL + flags:(NSDictionary *)flags; +/** + Calls setActiveDirectoryAppId:capability:redirectURL:flags: with nil flags. @param activeDirectoryAppId The application id. Must not be nil. - @param activeDirectoryScopes The scopes to be used with authentication. Must not be nil. + @param activeDirectoryCapabilty The capability to use for active directoy. Must not be nil. @param activeDirectoryRedirectURL The redirect url to be used with Azure Active Directory. Must not be nil. - @param activeDirectoryFlags A user defined dictionary to be passed through to the client when authenticated using the OneDrive for Business authentication flow. - @see https://dev.onedrive.com/auth/aad_oauth.htm */ + (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId - scopes:(NSArray *)activeDirectoryScopes - redirectURL:(NSString *)activeDirectoryRedirectURL - flags:(NSDictionary *)activeDirectoryFlags; + capability:(NSString *)activeDirectoryCapability + redirectURL:(NSString *)activeDirectoryRedirectURL; /** - Calls the setBusinessAppId:scopes:redirectURL:flags: with nil flags. + Calls setActiveDirectoryAppId:capability:redirectURL:flags: with nil flags. @param activeDirectoryAppId The application id. Must not be nil. - @param activeDirectoryScopes The scopes to be used with authentication. Must not be nil. + @param activeDirectoryResouceId The active directory reosuce id. Must not be nil. + @param activeDirectoryApiEndpoint The active directory api endpoint. Must not be nil. @param activeDirectoryRedirectURL The redirect url to be used with Azure Active Directory. Must not be nil. */ + (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId - scopes:(NSArray *)activeDirectoryScopes + resourceId:(NSString *)activeDirectoryResourceId + apiEndpoint:(NSString *)activeDirectoryApiEndpoint redirectURL:(NSString *)activeDirectoryRedirectURL; +/** + Sets the OneDrive for Business app information. + @param activeDirectoryAppId The application id. Must not be nil. + @param activeDirectoryCapability The active directory capability. Must not be nil if resouceId and apiEndpoint are nil. + @param activeDirectoryResouceId The active directroy resouceId. Must not be nil if capability is nil. + @param activeDirectoryApiEndpoint The active directory ApiEndpoing. Must not be nil if capability is nil. + @param activeDirectoryRedirectURL The redirect url to be used with Azure Active Directory. Must not be nil. + @param activeDirectoryFlags A user defined dictionary to be passed through to the client when authenticated using the OneDrive for Business authentication flow. + @see https://dev.onedrive.com/auth/aad_oauth.htm + */ ++ (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId + capability:(NSString *)activeDirectoryCapability + resourceId:(NSString *)activeDirectoryResourceId + apiEndpoint:(NSString *)activeDirectoryApiEndpoint + redirectURL:(NSString *)activeDirectoryRedirectURL + flags:(NSDictionary *)activeDirectoryFlags; + /** Calls the setActiveDirectoryAppId and setMicrosoftAccountAppId methods to set both microsoftAccounnt and Business application info. @param microsoftAccounntAppId The application id. Must not be nil. @param microsoftAccounntScopes The scopes to be used with authentication. Must not be nil. @param microsoftAccounntFlags A user defined dictionary to be passed through to the client when authenticated using the OneDrive microsoftAccounnt authentication flow. @param activeDirectoryAppId The application id. Must not be nil. - @param activeDirectoryScopes The scopes to be used with authentication. Must not be nil. + @param activeDirectoryCapabilty The active directroy capability must not be nil @param activeDirectoryRedirectURL The redirect url to be used with Azure Active Directory. Must not be nil. @param activeDirectoryFlags A user defined dictionary to be passed through to the client when authenticated using the OneDrive for Business authentication flow. */ @@ -107,10 +141,28 @@ microsoftAccountScopes:(NSArray *)microsoftAccounntScopes microsoftAccountFlags:(NSDictionary *)microsoftAccounntFlags activeDirectoryAppId:(NSString *)activeDirectoryAppId - activeDirectoryScopes:(NSArray *)activeDirectoryScopes + activeDirectoryCapability:(NSString *)activeDirectoryCapability activeDirectoryRedirectURL:(NSString *)activeDirectoryRedirectURL activeDirectoryFlags:(NSDictionary *)activeDirectoryFlags; - +/** + Calls the setActiveDirectoryAppId and setMicrosoftAccountAppId methods to set both microsoftAccounnt and Business application info. + @param microsoftAccounntAppId The application id. Must not be nil. + @param microsoftAccounntScopes The scopes to be used with authentication. Must not be nil. + @param microsoftAccounntFlags A user defined dictionary to be passed through to the client when authenticated using the OneDrive microsoftAccounnt authentication flow. + @param activeDirectoryAppId The application id. Must not be nil. + @param activeDirectoryResouceId The active directroy resource Id. Must not be nil. + @param activeDirectoryApiEndpoint The active directroy Api Endpoint. Must not be nil. + @param activeDirectoryRedirectURL The redirect url to be used with Azure Active Directory. Must not be nil. + @param activeDirectoryFlags A user defined dictionary to be passed through to the client when authenticated using the OneDrive for Business authentication flow. + */ ++ (void)setMicrosoftAccountAppId:(NSString *)microsoftAccounntAppId + microsoftAccountScopes:(NSArray *)microsoftAccounntScopes + microsoftAccountFlags:(NSDictionary *)microsoftAccounntFlags + activeDirectoryAppId:(NSString *)activeDirectoryAppId + activeDirectoryResourceId:(NSString *)activeDirectoryResourceId + activeDirectoryApiEndpoint:(NSString *)activeDirectoryApiEndpoint + activeDirectoryRedirectURL:(NSString *)activeDirectoryRedirectURL + activeDirectoryFlags:(NSDictionary *)activeDirectoryFlags; /** Sets the authentication provider. @param authProvider The auth provider. diff --git a/OneDriveSDK/Extensions/ODClient+DefaultConfiguration.m b/OneDriveSDK/Extensions/ODClient+DefaultConfiguration.m index a16f5dd..e44ae78 100644 --- a/OneDriveSDK/Extensions/ODClient+DefaultConfiguration.m +++ b/OneDriveSDK/Extensions/ODClient+DefaultConfiguration.m @@ -86,58 +86,136 @@ + (NSArray *)loadClients return [ODClient clientsFromAppConfig:[ODAppConfiguration defaultConfiguration]]; } - + (void)setMicrosoftAccountAppId:(NSString *)microsoftAccounntAppId scopes:(NSArray *)microsoftAccounntScopes flags:(NSDictionary *)microsoftAccounntFlags { NSParameterAssert(microsoftAccounntAppId); NSParameterAssert(microsoftAccounntScopes); - + // default to OneDrive + NSString *onedriveApiEndpoint = [NSString stringWithFormat:@"%@/%@", OD_MICROSOFT_ACCOUNT_ENDPOINT, OD_MICROSOFT_ACCOUNT_API_VERSION]; + [ODClient setMicrosoftAccountAppId:microsoftAccounntAppId + scopes:microsoftAccounntScopes + flags:microsoftAccounntFlags + apiEndpoint:onedriveApiEndpoint]; +} + ++ (void)setMicrosoftAccountAppId:(NSString *)microsoftAccounntAppId scopes:(NSArray *)microsoftAccounntScopes +{ + [ODClient setMicrosoftAccountAppId:microsoftAccounntAppId scopes:microsoftAccounntScopes flags:nil]; +} + ++ (void)setMicrosoftAccountAppId:(NSString *)microsoftAccounntAppId + scopes:(NSArray *)microsoftAccounntScopes + flags:(NSDictionary *)microsoftAccounntFlags + apiEndpoint:(NSString *)apiEndpoint +{ ODAppConfiguration *defaultConfig = [ODAppConfiguration defaultConfiguration]; defaultConfig.microsoftAccountAppId = microsoftAccounntAppId; defaultConfig.microsoftAccountScopes = microsoftAccounntScopes; defaultConfig.microsoftAccountFlags = microsoftAccounntFlags; + defaultConfig.microsoftAccountApiEndpoint = apiEndpoint; } -+ (void)setMicrosoftAccountAppId:(NSString *)microsoftAccounntAppId scopes:(NSArray *)microsoftAccounntScopes ++ (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId redirectURL:(NSString *)activeDirectoryRedirectURL { - [ODClient setMicrosoftAccountAppId:microsoftAccounntAppId scopes:microsoftAccounntScopes flags:nil]; + [ODClient setActiveDirectoryAppId:activeDirectoryAppId redirectURL:activeDirectoryRedirectURL flags:nil]; +} + ++ (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId + redirectURL:(NSString *)activeDirectoryRedirectURL + flags:(NSDictionary *)flags +{ + // Default to MyFiles for OneDrive for Business + [ODClient setActiveDirectoryAppId:activeDirectoryAppId + capability:@"MyFiles" + resourceId:nil + apiEndpoint:nil + redirectURL:activeDirectoryRedirectURL + flags:flags]; } + (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId - scopes:(NSArray *)activeDirectoryScopes + capability:(NSString *)activeDirectoryCapability + resourceId:(NSString *)activeDirectoryResourceId + apiEndpoint:(NSString *)activeDirectoryApiEndpoint redirectURL:(NSString *)activeDirectoryRedirectURL flags:(NSDictionary *)activeDirectoryFlags { NSParameterAssert(activeDirectoryAppId); - NSParameterAssert(activeDirectoryScopes); NSParameterAssert(activeDirectoryRedirectURL); ODAppConfiguration *defaultConfig = [ODAppConfiguration defaultConfiguration]; defaultConfig.activeDirectoryAppId = activeDirectoryAppId; - defaultConfig.activeDirectoryScopes = activeDirectoryScopes; + defaultConfig.activeDirectoryCapability = activeDirectoryCapability; defaultConfig.activeDirectoryRedirectURL = activeDirectoryRedirectURL; defaultConfig.activeDirectoryFlags = activeDirectoryFlags; + defaultConfig.activeDirectoryResourceId = activeDirectoryResourceId; + defaultConfig.activeDirectoryApiEndpointURL = activeDirectoryApiEndpoint; +} + ++ (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId + resourceId:(NSString *)activeDirectoryResourceId + apiEndpoint:(NSString *)activeDirectoryApiEndpoint + redirectURL:(NSString *)activeDirectoryRedirectURL +{ + NSParameterAssert(activeDirectoryResourceId); + + [ODClient setActiveDirectoryAppId:activeDirectoryAppId + capability:nil + resourceId:activeDirectoryResourceId + apiEndpoint:activeDirectoryApiEndpoint + redirectURL:activeDirectoryResourceId + flags:nil]; } + (void)setActiveDirectoryAppId:(NSString *)activeDirectoryAppId - scopes:(NSArray *)activeDirectoryScopes - redirectURL:(NSString *)activeDirectoryRedirectURL + capability:(NSString *)activeDirectoryCapability + redirectURL:(NSString *)activeDirectoryRedirectURL { - [ODClient setActiveDirectoryAppId:activeDirectoryAppId scopes:activeDirectoryScopes redirectURL:activeDirectoryRedirectURL flags:nil]; + NSParameterAssert(activeDirectoryCapability); + + [ODClient setActiveDirectoryAppId:activeDirectoryAppId + capability:activeDirectoryCapability + resourceId:nil + apiEndpoint:nil + redirectURL:activeDirectoryRedirectURL + flags:nil]; +} + ++ (void)setMicrosoftAccountAppId:(NSString *)microsoftAccounntAppId + microsoftAccountScopes:(NSArray *)microsoftAccounntScopes + microsoftAccountFlags:(NSDictionary *)microsoftAccounntFlags + activeDirectoryAppId:(NSString *)activeDirectoryAppId + activeDirectoryCapability:(NSString *)activeDirectoryCapability + activeDirectoryRedirectURL:(NSString *)activeDirectoryRedirectURL + activeDirectoryFlags:(NSDictionary *)activeDirectoryFlags +{ + [ODClient setMicrosoftAccountAppId:microsoftAccounntAppId scopes:microsoftAccounntScopes flags:microsoftAccounntFlags]; + [ODClient setActiveDirectoryAppId:activeDirectoryAppId + capability:activeDirectoryCapability + resourceId:nil + apiEndpoint:nil + redirectURL:activeDirectoryRedirectURL + flags:activeDirectoryFlags]; } + (void)setMicrosoftAccountAppId:(NSString *)microsoftAccounntAppId microsoftAccountScopes:(NSArray *)microsoftAccounntScopes microsoftAccountFlags:(NSDictionary *)microsoftAccounntFlags activeDirectoryAppId:(NSString *)activeDirectoryAppId - activeDirectoryScopes:(NSArray *)activeDirectoryScopes + activeDirectoryResourceId:(NSString *)activeDirectoryResourceId + activeDirectoryApiEndpoint:(NSString *)activeDirectoryApiEndpoint activeDirectoryRedirectURL:(NSString *)activeDirectoryRedirectURL activeDirectoryFlags:(NSDictionary *)activeDirectoryFlags { [ODClient setMicrosoftAccountAppId:microsoftAccounntAppId scopes:microsoftAccounntScopes flags:microsoftAccounntFlags]; - [ODClient setActiveDirectoryAppId:activeDirectoryAppId scopes:activeDirectoryScopes redirectURL:activeDirectoryRedirectURL flags:activeDirectoryFlags]; + [ODClient setActiveDirectoryAppId:activeDirectoryAppId + capability:nil + resourceId:activeDirectoryResourceId + apiEndpoint:activeDirectoryApiEndpoint + redirectURL:activeDirectoryRedirectURL + flags:activeDirectoryFlags]; } + (void)setAuthProvider:(id )authProvider diff --git a/OneDriveSDK/OneDriveCoreSDK/Core/ODConstants.h b/OneDriveSDK/OneDriveCoreSDK/Core/ODConstants.h index e2178ca..cb567a4 100644 --- a/OneDriveSDK/OneDriveCoreSDK/Core/ODConstants.h +++ b/OneDriveSDK/OneDriveCoreSDK/Core/ODConstants.h @@ -66,6 +66,5 @@ extern NSString *const ODHeaderPrefer; extern NSString *const ODHeaderContentType; extern NSString *const ODHeaderApplicationJson; extern NSString *const ODHeaderRespondAsync; -extern NSString *const ODSDKVersion; #endif diff --git a/OneDriveSDK/OneDriveCoreSDK/Core/ODConstants.m b/OneDriveSDK/OneDriveCoreSDK/Core/ODConstants.m index df5efe9..87b4f90 100644 --- a/OneDriveSDK/OneDriveCoreSDK/Core/ODConstants.m +++ b/OneDriveSDK/OneDriveCoreSDK/Core/ODConstants.m @@ -34,4 +34,3 @@ NSString *const ODHeaderContentType = @"Content-Type"; NSString *const ODHeaderApplicationJson = @"application/json"; NSString *const ODHeaderRespondAsync = @"respond-async"; -NSString *const ODSDKVersion = @"1.0.5"; diff --git a/OneDriveSDK/OneDriveCoreSDK/Core/ODObject.m b/OneDriveSDK/OneDriveCoreSDK/Core/ODObject.m index 381e467..8a12ada 100644 --- a/OneDriveSDK/OneDriveCoreSDK/Core/ODObject.m +++ b/OneDriveSDK/OneDriveCoreSDK/Core/ODObject.m @@ -21,6 +21,7 @@ #import "ODObject.h" +#import "NSDate+ODSerialization.h" @interface ODObject() @@ -59,8 +60,11 @@ - (NSDictionary*)dictionaryFromItem if ([obj respondsToSelector:@selector(dictionaryFromItem)]){ fullDictionary[key] = [obj dictionaryFromItem]; } + else if ([obj respondsToSelector:@selector(od_toString)]){ + fullDictionary[key] = [obj od_toString]; + } else{ - fullDictionary[key] = obj; + fullDictionary[key] = [obj description]; } }]; return fullDictionary; @@ -68,15 +72,7 @@ - (NSDictionary*)dictionaryFromItem - (NSDate *)dateFromString:(NSString *)dateString { - NSDate *date = nil; - if (dateString){ - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"]; - NSLocale *posix = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; - [dateFormatter setLocale:posix]; - date = [dateFormatter dateFromString:dateString]; - } - return date; + return [NSDate od_dateFromString:dateString]; } - (NSString *)description @@ -84,5 +80,6 @@ - (NSString *)description return [[self dictionaryFromItem] description]; } - @end + + diff --git a/OneDriveSDK/OneDriveCoreSDK/Core/ODRequest.m b/OneDriveSDK/OneDriveCoreSDK/Core/ODRequest.m index 52e9488..78ca25d 100644 --- a/OneDriveSDK/OneDriveCoreSDK/Core/ODRequest.m +++ b/OneDriveSDK/OneDriveCoreSDK/Core/ODRequest.m @@ -129,8 +129,6 @@ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60]; request.HTTPMethod = method; - - [request setValue:[NSString stringWithFormat:@"SDK-Version=iOS-v%@", ODSDKVersion] forHTTPHeaderField:@"X-RequestStats"]; if (body){ request.HTTPBody = body; diff --git a/OneDriveSDK/OneDriveCoreSDK/Core/ODURLSEssion/ODAsyncURLSessionDataTask.m b/OneDriveSDK/OneDriveCoreSDK/Core/ODURLSEssion/ODAsyncURLSessionDataTask.m index f96f634..98d349d 100644 --- a/OneDriveSDK/OneDriveCoreSDK/Core/ODURLSEssion/ODAsyncURLSessionDataTask.m +++ b/OneDriveSDK/OneDriveCoreSDK/Core/ODURLSEssion/ODAsyncURLSessionDataTask.m @@ -34,6 +34,8 @@ @interface ODAsyncURLSessionDataTask() @property (strong) NSMutableURLRequest *monitorRequest; +@property (strong) ODURLSessionTask *monitorTask; + @end @@ -63,17 +65,16 @@ - (NSURLSessionDataTask *)taskWithRequest:(NSMutableURLRequest *)request // If there was a client error set it [NSJSONSerialization dictionaryWithResponse:response responseData:data error:&error]; } - [self onRequestStarted:response error:error completion:self.asyncActionCompletion]; + [self onRequestStarted:response error:error]; } }]; } - (void)onRequestStarted:(NSURLResponse *)response error:(NSError *)error - completion:(void (^)(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error))completion { if (error){ - completion(nil, nil, error); + self.asyncActionCompletion(nil, nil, error); } else { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; @@ -85,51 +86,56 @@ - (void)onRequestStarted:(NSURLResponse *)response cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60]; - [self sendMonitorRequest:self.monitorRequest completion:completion]; + [self sendMonitorRequest:self.monitorRequest]; } else { // If the response was not ODAccepted and unknown error occurred - completion(nil, nil, [NSError errorWithDomain:ODErrorDomain code:ODUnknownError userInfo:@{ODHttpFailingResponseKey : httpResponse}]); + self.asyncActionCompletion(nil, nil, [NSError errorWithDomain:ODErrorDomain code:ODUnknownError userInfo:@{ODHttpFailingResponseKey : httpResponse}]); } } } -- (void)sendMonitorRequest:(NSMutableURLRequest *)request completion:(void (^)(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error))completion +- (void)sendMonitorRequest:(NSMutableURLRequest *)request; { - __block ODURLSessionDataTask *monitorRequest = [[ODURLSessionDataTask alloc] initWithRequest:request client:self.client completion:^(NSDictionary *response, NSError *error){ - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)monitorRequest.innerTask.response; - [self onMonitorRequestResponse:response httpResponse:httpResponse error:error completion:completion]; + __block ODURLSessionDataTask *task = [[ODURLSessionDataTask alloc] initWithRequest:request client:self.client completion:^(NSDictionary *response, NSError *error){ + [self onMonitorRequestResponse:response httpResponse:(NSHTTPURLResponse *)task.innerTask.response error:error]; + // We must set task to nil to drop the retain count from above. The task matains a strong reference to this call back which holds + // a refence to the asyncCompletionHandler which leads to a retain cycle. + task = nil; }]; - [monitorRequest execute]; + [task execute]; } - (void)onMonitorRequestResponse:(NSDictionary *)response httpResponse:(NSHTTPURLResponse *)httpResponse error:(NSError *)error - completion:(void (^)(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error))completion { ODAsyncOperationStatus *status = nil; if (!error){ - // When an async action returns it will redirect to the final location if (httpResponse.statusCode == ODOK){ _state = ODTaskCompleted; self.progress.completedUnitCount = 100; - completion(response, nil, nil); + // When an async action returns it will redirect to the final location + self.asyncActionCompletion(response, nil, nil); + self.asyncActionCompletion = nil; } - else if (response && httpResponse.statusCode == ODAccepted){ + else if (httpResponse.statusCode == ODAccepted){ status = [[ODAsyncOperationStatus alloc] initWithDictionary:response]; + [self.client.logger logWithLevel:ODLogInfo message:@"Async Status = %@", status]; self.progress.completedUnitCount = status.percentageComplete; - completion(nil, status, nil); + self.asyncActionCompletion(nil, status, nil); // if the response was a valid status report send another one - [self sendMonitorRequest:self.monitorRequest completion:completion]; + [self sendMonitorRequest:self.monitorRequest]; } else { NSError *unknownError = [NSError errorWithDomain:ODErrorDomain code:ODUnknownError userInfo:@{ODHttpFailingResponseKey : httpResponse }]; - completion(nil, nil, unknownError); + self.asyncActionCompletion(nil, nil, unknownError); + self.asyncActionCompletion = nil; } } else { - completion(nil, nil, error); + self.asyncActionCompletion(nil, nil, error); + self.asyncActionCompletion = nil; } } diff --git a/OneDriveSDK/OneDriveCoreSDK/Extensions/NSDate+ODSerialization.h b/OneDriveSDK/OneDriveCoreSDK/Extensions/NSDate+ODSerialization.h new file mode 100644 index 0000000..ee02787 --- /dev/null +++ b/OneDriveSDK/OneDriveCoreSDK/Extensions/NSDate+ODSerialization.h @@ -0,0 +1,30 @@ +// Copyright 2015 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import + +@interface NSDate (Serialization) + +- (NSString *)od_toString; + ++ (instancetype)od_dateFromString:(NSString *)dateString; + +@end diff --git a/OneDriveSDK/OneDriveCoreSDK/Extensions/NSDate+ODSerialization.m b/OneDriveSDK/OneDriveCoreSDK/Extensions/NSDate+ODSerialization.m new file mode 100644 index 0000000..b1dedb6 --- /dev/null +++ b/OneDriveSDK/OneDriveCoreSDK/Extensions/NSDate+ODSerialization.m @@ -0,0 +1,48 @@ +// Copyright 2015 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "NSDate+ODSerialization.h" + +@implementation NSDate (Serialization) + +- (NSString *)od_toString +{ + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"]; + NSLocale *posix = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; + [dateFormatter setLocale:posix]; + return [dateFormatter stringFromDate:self]; +} + ++ (instancetype)od_dateFromString:(NSString *)dateString +{ + NSDate *date = nil; + if (dateString){ + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"]; + NSLocale *posix = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; + [dateFormatter setLocale:posix]; + date = [dateFormatter dateFromString:dateString]; + } + return date; +} + +@end diff --git a/OneDriveSDK/OneDriveSDK.xcodeproj/project.pbxproj b/OneDriveSDK/OneDriveSDK.xcodeproj/project.pbxproj index 195965b..784ad6e 100644 --- a/OneDriveSDK/OneDriveSDK.xcodeproj/project.pbxproj +++ b/OneDriveSDK/OneDriveSDK.xcodeproj/project.pbxproj @@ -58,6 +58,9 @@ 1013FC491B68413A00BABCC1 /* ODItemContentRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1013FC471B68413A00BABCC1 /* ODItemContentRequest.m */; }; 1013FC501B6841BE00BABCC1 /* ODThumbnailContentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 1013FC4E1B6841BE00BABCC1 /* ODThumbnailContentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1013FC511B6841BE00BABCC1 /* ODThumbnailContentRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1013FC4F1B6841BE00BABCC1 /* ODThumbnailContentRequest.m */; }; + 10345C0C1BED2852000A3166 /* CannedItem.json in Resources */ = {isa = PBXBuildFile; fileRef = 10345C0B1BED2852000A3166 /* CannedItem.json */; }; + 10345C1C1BED5068000A3166 /* NSDate+ODSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 10345C1A1BED5068000A3166 /* NSDate+ODSerialization.h */; }; + 10345C1D1BED5068000A3166 /* NSDate+ODSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 10345C1B1BED5068000A3166 /* NSDate+ODSerialization.m */; }; 10492F9B1B6168A5004AB045 /* ODNSURLSessionTaskDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 10492F971B6168A5004AB045 /* ODNSURLSessionTaskDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 10492F9C1B6168A5004AB045 /* ODNSURLSessionTaskDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 10492F981B6168A5004AB045 /* ODNSURLSessionTaskDelegate.m */; }; 10492F9D1B6168A5004AB045 /* ODURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 10492F991B6168A5004AB045 /* ODURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -276,6 +279,8 @@ 10B4D2E71AF821C40083D86C /* ODThumbnailSetRequestBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 10B4D20F1AF821C40083D86C /* ODThumbnailSetRequestBuilder.m */; }; 10B4D3331AF827D80083D86C /* OneDriveSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 10B4D1201AF8215D0083D86C /* OneDriveSDK.framework */; }; 10C001611B4397D200B4BCC4 /* ODLoggerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 10C001601B4397D200B4BCC4 /* ODLoggerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 10E216CE1BEBF9F800EF108B /* ODServiceInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 10E216CD1BEBF9F800EF108B /* ODServiceInfoTests.m */; }; + 10E216D41BEBFA0900EF108B /* ODServiceInfoProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 10E216D31BEBFA0900EF108B /* ODServiceInfoProviderTests.m */; }; 10F823401B59D467008F74DE /* ODVersionsCollectionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 10F8233C1B59D467008F74DE /* ODVersionsCollectionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; 10F823411B59D467008F74DE /* ODVersionsCollectionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 10F8233D1B59D467008F74DE /* ODVersionsCollectionRequest.m */; }; 10F823421B59D467008F74DE /* ODVersionsCollectionRequestBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 10F8233E1B59D467008F74DE /* ODVersionsCollectionRequestBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -344,11 +349,11 @@ 07F15415D48153E70243F2B4 /* libPods-OneDriveSDK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OneDriveSDK.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 10007C641B30818F00E4ED17 /* ODAuth.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ODAuth.h; sourceTree = ""; }; 10007C6D1B309D5200E4ED17 /* ODAppConfiguration+DefaultConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "ODAppConfiguration+DefaultConfiguration.h"; path = "../Extensions/ODAppConfiguration+DefaultConfiguration.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 10007C6E1B309D5200E4ED17 /* ODAppConfiguration+DefaultConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = "ODAppConfiguration+DefaultConfiguration.m"; path = "../Extensions/ODAppConfiguration+DefaultConfiguration.m"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 10007C6E1B309D5200E4ED17 /* ODAppConfiguration+DefaultConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = "ODAppConfiguration+DefaultConfiguration.m"; path = "../Extensions/ODAppConfiguration+DefaultConfiguration.m"; sourceTree = ""; }; 10007C7E1B332A6A00E4ED17 /* ODClient+Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "ODClient+Authentication.h"; path = "../Extensions/ODClient+Authentication.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 10007C7F1B332A6A00E4ED17 /* ODClient+Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = "ODClient+Authentication.m"; path = "../Extensions/ODClient+Authentication.m"; sourceTree = ""; }; 10007C821B332BBD00E4ED17 /* ODClient+DefaultConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "ODClient+DefaultConfiguration.h"; path = "../Extensions/ODClient+DefaultConfiguration.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 10007C831B332BBD00E4ED17 /* ODClient+DefaultConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = "ODClient+DefaultConfiguration.m"; path = "../Extensions/ODClient+DefaultConfiguration.m"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 10007C831B332BBD00E4ED17 /* ODClient+DefaultConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = "ODClient+DefaultConfiguration.m"; path = "../Extensions/ODClient+DefaultConfiguration.m"; sourceTree = ""; }; 10007C8E1B33609100E4ED17 /* ODError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ODError.h; path = ../Errors/ODError.h; sourceTree = ""; }; 10007C8F1B33609100E4ED17 /* ODError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ODError.m; path = ../Errors/ODError.m; sourceTree = ""; }; 10007C921B336AA700E4ED17 /* ODErrorCodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ODErrorCodes.h; path = ../Errors/ODErrorCodes.h; sourceTree = ""; }; @@ -358,7 +363,7 @@ 1003AABA1B0A82F30039017A /* ODKeychainWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ODKeychainWrapper.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 1003AABD1B0A884D0039017A /* ODAccountStoreTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ODAccountStoreTests.m; path = AuthTests/ODAccountStoreTests.m; sourceTree = ""; }; 1003AABF1B0BF2750039017A /* ODAsyncURLSessionDataTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ODAsyncURLSessionDataTask.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 1003AAC01B0BF2750039017A /* ODAsyncURLSessionDataTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ODAsyncURLSessionDataTask.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 1003AAC01B0BF2750039017A /* ODAsyncURLSessionDataTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ODAsyncURLSessionDataTask.m; sourceTree = ""; }; 1003AAC31B0BF30D0039017A /* ODURLSessionTask+Protected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ODURLSessionTask+Protected.h"; sourceTree = ""; }; 1003AAC41B0BF3DF0039017A /* ODURLSessionProgressTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ODURLSessionProgressTask.h; sourceTree = ""; }; 1003AAC51B0BF3DF0039017A /* ODURLSessionProgressTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ODURLSessionProgressTask.m; sourceTree = ""; }; @@ -395,6 +400,9 @@ 1013FC471B68413A00BABCC1 /* ODItemContentRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ODItemContentRequest.m; sourceTree = ""; }; 1013FC4E1B6841BE00BABCC1 /* ODThumbnailContentRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ODThumbnailContentRequest.h; sourceTree = ""; }; 1013FC4F1B6841BE00BABCC1 /* ODThumbnailContentRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ODThumbnailContentRequest.m; sourceTree = ""; }; + 10345C0B1BED2852000A3166 /* CannedItem.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CannedItem.json; sourceTree = ""; }; + 10345C1A1BED5068000A3166 /* NSDate+ODSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+ODSerialization.h"; sourceTree = ""; }; + 10345C1B1BED5068000A3166 /* NSDate+ODSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+ODSerialization.m"; sourceTree = ""; }; 10492F971B6168A5004AB045 /* ODNSURLSessionTaskDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ODNSURLSessionTaskDelegate.h; sourceTree = ""; }; 10492F981B6168A5004AB045 /* ODNSURLSessionTaskDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ODNSURLSessionTaskDelegate.m; sourceTree = ""; }; 10492F991B6168A5004AB045 /* ODURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ODURLSessionManager.h; sourceTree = ""; }; @@ -617,6 +625,8 @@ 10C001601B4397D200B4BCC4 /* ODLoggerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ODLoggerProtocol.h; path = Common/ODLoggerProtocol.h; sourceTree = SOURCE_ROOT; }; 10CE79A31AF97EA000033B40 /* ODTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ODTestCase.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 10CE79A41AF97EA000033B40 /* ODTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ODTestCase.m; sourceTree = ""; }; + 10E216CD1BEBF9F800EF108B /* ODServiceInfoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ODServiceInfoTests.m; path = AuthTests/ODServiceInfoTests.m; sourceTree = ""; }; + 10E216D31BEBFA0900EF108B /* ODServiceInfoProviderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ODServiceInfoProviderTests.m; path = AuthTests/ODServiceInfoProviderTests.m; sourceTree = ""; }; 10F8233C1B59D467008F74DE /* ODVersionsCollectionRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ODVersionsCollectionRequest.h; sourceTree = ""; }; 10F8233D1B59D467008F74DE /* ODVersionsCollectionRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ODVersionsCollectionRequest.m; sourceTree = ""; }; 10F8233E1B59D467008F74DE /* ODVersionsCollectionRequestBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ODVersionsCollectionRequestBuilder.h; sourceTree = ""; }; @@ -684,6 +694,8 @@ 104AC3901B41B80C009EEB0F /* Extensions */ = { isa = PBXGroup; children = ( + 10345C1A1BED5068000A3166 /* NSDate+ODSerialization.h */, + 10345C1B1BED5068000A3166 /* NSDate+ODSerialization.m */, 101103D71B1693B700A83BAB /* NSJSONSerialization+ResponseHelper.h */, 101103D81B1693B700A83BAB /* NSJSONSerialization+ResponseHelper.m */, 100D33E01B3DE090003576F7 /* ODThumbnailSet+CustomThumbnail.h */, @@ -722,6 +734,8 @@ 10A19D051B03E59D00E69443 /* ODAuthHelperTests.m */, 10A19D381B065A1100E69443 /* ODPersonalAuthProviderTests.m */, 1003AABD1B0A884D0039017A /* ODAccountStoreTests.m */, + 10E216CD1BEBF9F800EF108B /* ODServiceInfoTests.m */, + 10E216D31BEBFA0900EF108B /* ODServiceInfoProviderTests.m */, ); name = AuthUnitTests; sourceTree = ""; @@ -1105,6 +1119,7 @@ isa = PBXGroup; children = ( 10B4D3301AF827D80083D86C /* Info.plist */, + 10345C0B1BED2852000A3166 /* CannedItem.json */, ); name = "Supporting Files"; sourceTree = ""; @@ -1258,6 +1273,7 @@ 10B4D2E61AF821C40083D86C /* ODThumbnailSetRequestBuilder.h in Headers */, 10B4D2E41AF821C40083D86C /* ODThumbnailSetRequest.h in Headers */, 10B4D2721AF821C40083D86C /* ODOpenWithSet.h in Headers */, + 10345C1C1BED5068000A3166 /* NSDate+ODSerialization.h in Headers */, 10B4D2571AF821C40083D86C /* ODChunkedUploadSessionDescriptor.h in Headers */, 10B4D23C1AF821C40083D86C /* ODURLSessionDataTask.h in Headers */, 10B4D26D1AF821C40083D86C /* ODLocation.h in Headers */, @@ -1459,6 +1475,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 10345C0C1BED2852000A3166 /* CannedItem.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1591,6 +1608,7 @@ 101104131B1E8F9400A83BAB /* ODBaseAuthProvider.m in Sources */, 10B4D24B1AF821C40083D86C /* ODIfNoneMatch.m in Sources */, 10B4D2521AF821C40083D86C /* ODSelectOptions.m in Sources */, + 10345C1D1BED5068000A3166 /* NSDate+ODSerialization.m in Sources */, 10007C911B33609100E4ED17 /* ODError.m in Sources */, 10B4D22D1AF821C40083D86C /* ODCollection.m in Sources */, 10B4D2DB1AF821C40083D86C /* ODSharesCollectionRequestBuilder.m in Sources */, @@ -1672,6 +1690,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 10E216CE1BEBF9F800EF108B /* ODServiceInfoTests.m in Sources */, 10702EA51B600A0C001A85FF /* ODURLSessionTaskTests.m in Sources */, 10702E9D1B600A0C001A85FF /* ODActionsTests.m in Sources */, 10702E9F1B600A0C001A85FF /* ODItemRequestTests.m in Sources */, @@ -1680,6 +1699,7 @@ 10702EA61B600A16001A85FF /* ODAuthHelperTests.m in Sources */, 10702EA71B600A16001A85FF /* ODPersonalAuthProviderTests.m in Sources */, 10702EA81B600A16001A85FF /* ODAccountStoreTests.m in Sources */, + 10E216D41BEBFA0900EF108B /* ODServiceInfoProviderTests.m in Sources */, 10702EA11B600A0C001A85FF /* ODLoggerTests.m in Sources */, 10702EA31B600A0C001A85FF /* ODRequestOptionsTests.m in Sources */, 10702EA21B600A0C001A85FF /* ODObjectTests.m in Sources */, diff --git a/OneDriveSDK/OneDriveSDKTests/AuthTests/ODServiceInfoProviderTests.m b/OneDriveSDK/OneDriveSDKTests/AuthTests/ODServiceInfoProviderTests.m new file mode 100644 index 0000000..915edd6 --- /dev/null +++ b/OneDriveSDK/OneDriveSDKTests/AuthTests/ODServiceInfoProviderTests.m @@ -0,0 +1,159 @@ +// Copyright 2015 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "ODTestCase.h" +#import "ODServiceInfoProvider.h" +#import "ODServiceInfo.h" +#import "ODAppConfiguration.h" + +@interface ODServiceInfoProvider() + +- (ODServiceInfo *)serviceInfoFromDiscoveryResponse:(NSURL *)url appConfig:(ODAppConfiguration *)appConfig error:(NSError * __autoreleasing *)error; + +@end + +@interface ODServiceInfoProviderTests : ODTestCase + +@property ODServiceInfoProvider *serviceInfoProvider; + +@end + +@implementation ODServiceInfoProviderTests + +- (void)setUp { + [super setUp]; + self.serviceInfoProvider = [[ODServiceInfoProvider alloc] init]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testGetMSAServiceInfo{ + ODAppConfiguration *appconfig = [[ODAppConfiguration alloc] init]; + appconfig.microsoftAccountAppId = @"foo"; + appconfig.microsoftAccountScopes = @[]; + + [self.serviceInfoProvider getServiceInfoWithViewController:[[UIViewController alloc] init] + appConfiguration:appconfig + completion:^(UIViewController *vc, ODServiceInfo *serviceInfo, NSError *error){ + XCTAssertNil(error); + XCTAssertEqual(serviceInfo.accountType, ODMSAAccount); + }]; +} + +- (void)testGetAADServiceInfoNoResourceId{ + ODAppConfiguration *appconfig = [[ODAppConfiguration alloc] init]; + appconfig.activeDirectoryAppId = @"foo"; + appconfig.activeDirectoryRedirectURL = @"bar"; + + [self.serviceInfoProvider getServiceInfoWithViewController:[[UIViewController alloc] init] + appConfiguration:appconfig + completion:^(UIViewController *vc, ODServiceInfo *serviceInfo, NSError *error){ + XCTAssertNil(error); + XCTAssertEqual(serviceInfo.accountType, ODADAccount); + XCTAssertEqual(serviceInfo.resourceId, OD_DISCOVERY_SERVICE_RESOURCEID); + }]; +} + +- (void)testGetAADServiceInfoResourceId{ + ODAppConfiguration *appconfig = [[ODAppConfiguration alloc] init]; + appconfig.activeDirectoryAppId = @"foo"; + appconfig.activeDirectoryRedirectURL = @"bar"; + appconfig.activeDirectoryResourceId = @"quz"; + + [self.serviceInfoProvider getServiceInfoWithViewController:[[UIViewController alloc] init] + appConfiguration:appconfig + completion:^(UIViewController *vc, ODServiceInfo *serviceInfo, NSError *error){ + XCTAssertNil(error); + XCTAssertEqual(serviceInfo.accountType, ODADAccount); + XCTAssertEqual(serviceInfo.resourceId, appconfig.activeDirectoryResourceId); + }]; +} + +- (void)testGetAADServiceInfoFromDisambiguationResponse{ + ODAppConfiguration *appconfig = [[ODAppConfiguration alloc] init]; + appconfig.activeDirectoryAppId = @"foo"; + appconfig.activeDirectoryRedirectURL = @"bar"; + + NSString *email = @"baz"; + NSURL *resposneURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/?%@=%@&%@=%@", + OD_DISCOVERY_REDIRECT_URL, + OD_AUTH_USER_EMAIL, + email, + OD_DISCOVERY_ACCOUNT_TYPE, + OD_DISCOVERY_ACCOUNT_TYPE_AAD]]; + + ODServiceInfo *serviceInfo = [self.serviceInfoProvider serviceInfoFromDiscoveryResponse:resposneURL appConfig:appconfig error:nil]; + + XCTAssertNotNil(serviceInfo); + XCTAssertEqual(serviceInfo.accountType, ODADAccount); + XCTAssertEqualObjects(serviceInfo.userEmail, email); +} + +- (void)testGetMSAServiceInfoFromDisamabiguationResposne{ + + ODAppConfiguration *appconfig = [[ODAppConfiguration alloc] init]; + appconfig.microsoftAccountAppId = @"foo"; + appconfig.microsoftAccountScopes = @[]; + + NSString *email = @"baz"; + NSURL *resposneURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/?%@=%@&%@=%@", + OD_DISCOVERY_REDIRECT_URL, + OD_AUTH_USER_EMAIL, + email, + OD_DISCOVERY_ACCOUNT_TYPE, + OD_DISCOVERY_ACCOUNT_TYPE_MSA]]; + + ODServiceInfo *serviceInfo = [self.serviceInfoProvider serviceInfoFromDiscoveryResponse:resposneURL appConfig:appconfig error:nil]; + + XCTAssertNotNil(serviceInfo); + XCTAssertEqual(serviceInfo.accountType, ODMSAAccount); + XCTAssertEqualObjects(serviceInfo.userEmail, email); +} + +- (void)testGetInvalidServiceInfoFromDisambiguationResponse{ + ODAppConfiguration *appconfig = [[ODAppConfiguration alloc] init]; + appconfig.microsoftAccountAppId = @"foo"; + appconfig.microsoftAccountScopes = @[]; + + NSString *email = @"baz"; + NSURL *resposneURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/?%@=%@&%@=%@", + OD_DISCOVERY_REDIRECT_URL, + OD_AUTH_USER_EMAIL, + email, + OD_DISCOVERY_ACCOUNT_TYPE, + OD_DISCOVERY_ACCOUNT_TYPE_AAD]]; + NSError *error = nil; + ODServiceInfo *serviceInfo = [self.serviceInfoProvider serviceInfoFromDiscoveryResponse:resposneURL + appConfig:appconfig + error:&error]; + + XCTAssertNil(serviceInfo); + XCTAssertNotNil(error); +} + + + + +@end diff --git a/OneDriveSDK/OneDriveSDKTests/AuthTests/ODServiceInfoTests.m b/OneDriveSDK/OneDriveSDKTests/AuthTests/ODServiceInfoTests.m new file mode 100644 index 0000000..2250c80 --- /dev/null +++ b/OneDriveSDK/OneDriveSDKTests/AuthTests/ODServiceInfoTests.m @@ -0,0 +1,63 @@ +// Copyright 2015 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "ODTestCase.h" +#import "ODServiceInfo+Protected.h" +#import "ODAADServiceInfo.h" +#import "ODMSAServiceInfo.h" + +@interface ODServiceInfoTests : ODTestCase + +@property NSCoder *mockDecoder; + +@end + +@implementation ODServiceInfoTests + +- (void)setUp { + [super setUp]; + self.mockDecoder = OCMClassMock([NSCoder class]); + OCMStub([self.mockDecoder decodeObjectForKey:@"apiEndpiint"]).andReturn(nil); + OCMStub([self.mockDecoder decodeObjectForKey:@"resourceId"]).andReturn(OD_MICROSOFT_ACCOUNT_ENDPOINT); + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +/** + Make sure the migrations from resourceId to apiEndpoint works + */ +- (void)testAADInitFromCoder{ + ODAADServiceInfo *serviceInfo = [[ODAADServiceInfo alloc] initWithCoder:self.mockDecoder]; + XCTAssertNotNil(serviceInfo.apiEndpoint); + XCTAssertTrue([serviceInfo.apiEndpoint containsString:OD_ACTIVE_DIRECTORY_URL_SUFFIX]); +} + +- (void)testMSAInitFromCoder{ + ODMSAServiceInfo *serviceInfo = [[ODMSAServiceInfo alloc] initWithCoder:self.mockDecoder]; + XCTAssertNotNil(serviceInfo.apiEndpoint); + XCTAssertEqualObjects(serviceInfo.apiEndpoint, serviceInfo.resourceId); +} + +@end diff --git a/OneDriveSDK/OneDriveSDKTests/CannedItem.json b/OneDriveSDK/OneDriveSDKTests/CannedItem.json new file mode 100644 index 0000000..cb13f5b --- /dev/null +++ b/OneDriveSDK/OneDriveSDKTests/CannedItem.json @@ -0,0 +1,55 @@ +{ + "@odata.context": "https://api.onedrive.com/v1.0/$metadata#drives('me')/items/$entity", + "createdBy": { + "application": { + "displayName": "Test_OneDriveSdk", + "id": "4011dc49" + }, + "user": { + "displayName": "Ace Levenberg", + "id": "1234EEEE777" + } + }, + "createdDateTime": "2015-05-20T21:14:01.077Z", + "cTag": "aYzpFRTVEMEYyRkRGNUQ4MjczITU5MTUyLjI1OA", + "eTag": "aRUU1RDBGMkZERjVEODI3MyE1OTE1Mi4y", + "id": "1234EEEE777!59152", + "lastModifiedBy": { + "application": { + "displayName": "OneDrive Explorer for iOS (sample app)", + "id": "48160af8" + }, + "user": { + "displayName": "Ace Levenberg", + "id": "1234EEEE777" + } + }, + "lastModifiedDateTime": "2015-09-04T01:26:23.79Z", + "name": "fooFile.txt", + "parentReference": { + "driveId": "1234EEEE777", + "id": "1234EEEE777!46068", + "path": "/drive/root:/fooFolder" + }, + "size": 7, + "webUrl": "https://onedrive.live.com/redir?resid=EE5D0F2FDF5D8273!59152", + "file": { + "hashes": { + "crc32Hash": "54EB1E07", + "sha1Hash": "107E5F2E03223A8DBDD1E641BB9F75D07E7B4CEB" + }, + "mimeType": "text/plain" + }, + "fileSystemInfo": { + "createdDateTime": "2015-05-20T21:14:01.077Z", + "lastModifiedDateTime": "2015-09-04T01:26:23.727Z" + }, + "shared": { + "owner": { + "user": { + "displayName": "Ace Levenberg", + "id": "1234EEEE777" + } + } + } +} \ No newline at end of file diff --git a/OneDriveSDK/OneDriveSDKTests/CoreUnitTests/ODObjectTests.m b/OneDriveSDK/OneDriveSDKTests/CoreUnitTests/ODObjectTests.m index 0a9b23e..586daf3 100644 --- a/OneDriveSDK/OneDriveSDKTests/CoreUnitTests/ODObjectTests.m +++ b/OneDriveSDK/OneDriveSDKTests/CoreUnitTests/ODObjectTests.m @@ -38,18 +38,28 @@ - (void)tearDown { [super tearDown]; } + - (void)testNilDictionary{ XCTAssertNil([[ODObject alloc] initWithDictionary:nil]); } - (void)testItemFromDictionary{ - NSString *itemId = @"12345"; - ODItem *testItem = [[ODItem alloc] initWithDictionary:@{ @"id" : itemId}]; + ODItem *testItem = [[ODItem alloc] initWithDictionary:self.cannedItem]; - XCTAssertEqualObjects(testItem.id, itemId); + XCTAssertEqualObjects(testItem.id, self.cannedItem[@"id"]); + XCTAssertNotNil(testItem.fileSystemInfo); + XCTAssertNotNil(testItem.fileSystemInfo.createdDateTime); XCTAssertNil(testItem.folder); } +- (void)testItemFromDictionaryToJson{ + ODItem *testItem = [[ODItem alloc] initWithDictionary:self.cannedItem]; + NSError *error; + NSData *jsonBlob = [NSJSONSerialization dataWithJSONObject:[testItem dictionaryFromItem] options:0 error:&error]; + XCTAssertNotNil(jsonBlob); + XCTAssertNil(error); +} + - (void)testFolder{ NSString *itemId = @"12345"; NSDictionary *folder = @{ @"childCount" : @"42"}; @@ -124,5 +134,25 @@ - (void)testSetDate{ XCTAssertNotNil(testItem.fileSystemInfo.createdDateTime); } +- (void)testSerializeSetDate{ + NSDate *now = [NSDate dateWithTimeIntervalSince1970:0]; + ODItem *testItem = [[ODItem alloc] init]; + testItem.fileSystemInfo = [[ODFileSystemInfo alloc] init]; + testItem.fileSystemInfo.createdDateTime = [now copy]; + + NSDictionary *itemDictionary = [testItem dictionaryFromItem]; + XCTAssertNotNil(itemDictionary[@"fileSystemInfo"][@"createdDateTime"]); +} + +- (void)testJsonSerializationItemWithChangedDate{ + NSDate *now = [NSDate dateWithTimeIntervalSince1970:0]; + ODItem *cannedItem = [[ODItem alloc] initWithDictionary:self.cannedItem]; + cannedItem.fileSystemInfo.createdDateTime = now; + NSError *error = nil; + NSData *jsonBlob = [NSJSONSerialization dataWithJSONObject:[cannedItem dictionaryFromItem] options:0 error:&error]; + XCTAssertNotNil(jsonBlob); + XCTAssertNil(error); +} + @end diff --git a/OneDriveSDK/OneDriveSDKTests/CoreUnitTests/ODURLSessionTaskTests.m b/OneDriveSDK/OneDriveSDKTests/CoreUnitTests/ODURLSessionTaskTests.m index 5f5cf5a..6e2067f 100644 --- a/OneDriveSDK/OneDriveSDKTests/CoreUnitTests/ODURLSessionTaskTests.m +++ b/OneDriveSDK/OneDriveSDKTests/CoreUnitTests/ODURLSessionTaskTests.m @@ -53,16 +53,16 @@ @interface ODAsyncURLSessionDataTask() @property NSMutableURLRequest *monitorRequest; +@property (strong) ODAsyncActionCompletion asyncActionCompletion; + - (void)onRequestStarted:(NSURLResponse *)response - error:(NSError *)error - completion:(void (^)(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error))completion; + error:(NSError *)error; -- (void)sendMonitorRequest:(NSMutableURLRequest *)request completion:(void (^)(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error))completion; +- (void)sendMonitorRequest:(NSMutableURLRequest *)request; - (void)onMonitorRequestResponse:(NSDictionary *)response httpResponse:(NSHTTPURLResponse *)httpResponse - error:(NSError *)error - completion:(void (^)(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error))completion; + error:(NSError *)error; @end @@ -341,22 +341,24 @@ - (void)testAsyncTaskValidAsyncSessionCreated{ ODAsyncURLSessionDataTask *asyncTask = [[ODAsyncURLSessionDataTask alloc] initWithRequest:self.mockRequest client:self.mockClient completion:nil]; ODAsyncURLSessionDataTask *mockTask = OCMPartialMock(asyncTask); - OCMStub([mockTask sendMonitorRequest:[OCMArg any] completion:nil]); - [mockTask onRequestStarted:accepted error:nil completion:nil]; + OCMStub([mockTask sendMonitorRequest:[OCMArg any]]); + [mockTask onRequestStarted:accepted error:nil]; OCMVerify([mockTask sendMonitorRequest:[OCMArg checkWithBlock:^(NSMutableURLRequest *request){ - return [[request.URL absoluteString] isEqualToString:[self.testBaseURL absoluteString]];}] - completion:nil]); + return [[request.URL absoluteString] isEqualToString:[self.testBaseURL absoluteString]]; + }]]); } - (void)testAsyncTaskOnMonitorRequestError{ ODAsyncURLSessionDataTask *asyncTask = [[ODAsyncURLSessionDataTask alloc] initWithRequest:self.mockRequest client:self.mockClient]; __block NSError *unknownError = [NSError errorWithDomain:ODErrorDomain code:ODUnknownError userInfo:@{}]; - [asyncTask onMonitorRequestResponse:nil httpResponse:nil error:unknownError completion:^(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error){ + asyncTask.asyncActionCompletion = ^(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error){ XCTAssertNil(response); XCTAssertNil(status); XCTAssertEqual(error, unknownError); - }]; + }; + + [asyncTask onMonitorRequestResponse:nil httpResponse:nil error:unknownError]; } - (void)testAsyncTaskValidMonitorUpdate{ @@ -369,26 +371,30 @@ - (void)testAsyncTaskValidMonitorUpdate{ ODAsyncURLSessionDataTask *mockTask = OCMPartialMock(asyncTask); mockTask.monitorRequest = self.mockRequest; - OCMStub([mockTask sendMonitorRequest:[OCMArg any] completion:[OCMArg any]]); - [mockTask onMonitorRequestResponse:[mockStatus dictionaryFromItem] httpResponse:response error:nil completion:^(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error){ + OCMStub([mockTask sendMonitorRequest:[OCMArg any]]); + + + mockTask.asyncActionCompletion = ^(NSDictionary *response, ODAsyncOperationStatus *status, NSError *error){ XCTAssertNil(response); XCTAssertNil(error); XCTAssertEqualObjects(status.status, mockStatus.status); XCTAssertEqualObjects(status.operation, mockStatus.operation); XCTAssertEqual(status.percentageComplete, mockStatus.percentageComplete); - }]; - + }; + [mockTask onMonitorRequestResponse:[mockStatus dictionaryFromItem] httpResponse:response error:nil]; XCTAssertEqual(mockTask.progress.completedUnitCount, mockStatus.percentageComplete); - OCMVerify([mockTask sendMonitorRequest:self.mockRequest completion:[OCMArg any]]); + OCMVerify([mockTask sendMonitorRequest:self.mockRequest]); } - (void)testAsyncTaskValidItemReturned{ - ODAsyncURLSessionDataTask *asyncTask = [[ODAsyncURLSessionDataTask alloc] initWithRequest:self.mockRequest client:self.mockClient completion:nil]; ODItem *mockItem = [[ODItem alloc] init]; mockItem.name = @"foo"; mockItem.id = @"bar"; NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.testBaseURL statusCode:ODOK HTTPVersion:@"foo" headerFields:nil]; - [asyncTask onMonitorRequestResponse:[mockItem dictionaryFromItem] httpResponse:response error:nil completion:^(NSDictionary *dictionary, ODAsyncOperationStatus *status, NSError *error){ + + ODAsyncURLSessionDataTask *asyncTask = [[ODAsyncURLSessionDataTask alloc] initWithRequest:self.mockRequest + client:self.mockClient + completion:^(NSDictionary *dictionary, ODAsyncOperationStatus *status, NSError *error){ XCTAssertNil(status); XCTAssertNil(error); XCTAssertNotNil(dictionary); @@ -396,17 +402,18 @@ - (void)testAsyncTaskValidItemReturned{ XCTAssertEqualObjects(receivedItem.id, mockItem.id); XCTAssertEqualObjects(receivedItem.name, mockItem.name); }]; + [asyncTask onMonitorRequestResponse:[mockItem dictionaryFromItem] httpResponse:response error:nil]; XCTAssertEqual(asyncTask.progress.completedUnitCount, 100); XCTAssertEqual(asyncTask.state, ODTaskCompleted); } - (void)testAsyncTaskInvalidResponse{ - ODAsyncURLSessionDataTask *asyncTask = [[ODAsyncURLSessionDataTask alloc] initWithRequest:self.mockRequest client:self.mockClient completion:nil]; - - NSHTTPURLResponse *badResponse = [[NSHTTPURLResponse alloc] initWithURL:self.testBaseURL statusCode:42 HTTPVersion:@"foo" headerFields:@{}]; - [asyncTask onMonitorRequestResponse:nil httpResponse:badResponse error:nil completion:^(NSDictionary *dictionary, ODAsyncOperationStatus *status, NSError *error) { + ODAsyncURLSessionDataTask *asyncTask = [[ODAsyncURLSessionDataTask alloc] initWithRequest:self.mockRequest client:self.mockClient completion:^(NSDictionary *resposne, ODAsyncOperationStatus *status, NSError *error){ XCTAssertNotNil(error); }]; + + NSHTTPURLResponse *badResponse = [[NSHTTPURLResponse alloc] initWithURL:self.testBaseURL statusCode:42 HTTPVersion:@"foo" headerFields:@{}]; + [asyncTask onMonitorRequestResponse:nil httpResponse:badResponse error:nil]; } diff --git a/OneDriveSDK/OneDriveSDKTests/ODTestCase.h b/OneDriveSDK/OneDriveSDKTests/ODTestCase.h index d7d9378..f171e68 100644 --- a/OneDriveSDK/OneDriveSDKTests/ODTestCase.h +++ b/OneDriveSDK/OneDriveSDKTests/ODTestCase.h @@ -33,6 +33,8 @@ @property ODClient *mockClient; +@property (readonly, nonatomic) NSDictionary *cannedItem; + @property id mockSession; @property id mockAuthProvider; diff --git a/OneDriveSDK/OneDriveSDKTests/ODTestCase.m b/OneDriveSDK/OneDriveSDKTests/ODTestCase.m index 9df8abe..678beb2 100644 --- a/OneDriveSDK/OneDriveSDKTests/ODTestCase.m +++ b/OneDriveSDK/OneDriveSDKTests/ODTestCase.m @@ -22,14 +22,22 @@ #import "ODTestCase.h" +@interface ODTestCase(){ + NSDictionary *_cannedItem; +} + +@end + @implementation ODTestCase + + - (void)setUp{ [super setUp]; self.mockSession = OCMProtocolMock(@protocol(ODHttpProvider)); self.mockAuthProvider = OCMProtocolMock(@protocol(ODAuthProvider)); self.mockClient = OCMPartialMock([[ODClient alloc] initWithURL:[self.testBaseURL absoluteString] httpProvider:self.mockSession authProvider:self.mockAuthProvider]); - self.testBaseURL = [NSURL URLWithString:@"https://foo.com/bar/baz"]; + self.testBaseURL = [NSURL URLWithString:@"https://foo.com/bar/baz"]; } - (void) setAuthProvider:(id )mockAuthProvider @@ -205,10 +213,26 @@ - (void)assertRequest:(NSURLRequest *)request isEqual:(NSURLRequest *)expectedRe XCTAssertEqualObjects(request.HTTPMethod, expectedRequest.HTTPMethod); XCTAssertEqualObjects(request.HTTPBody, expectedRequest.HTTPBody); // all requests that were made have the SDK version on them - XCTAssertEqual([request.allHTTPHeaderFields count], [expectedRequest.allHTTPHeaderFields count] + 1); + XCTAssertEqual([request.allHTTPHeaderFields count], [expectedRequest.allHTTPHeaderFields count]); [expectedRequest.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop){ XCTAssertEqualObjects(request.allHTTPHeaderFields[key], value); }]; } +- (NSDictionary *)cannedItem +{ + if (!_cannedItem){ + __block id class = [self class]; + static NSDictionary *cannedItem = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *cannedItemPath = [[NSBundle bundleForClass:class] pathForResource:@"CannedItem" ofType:@"json"]; + NSData *cannedItemData = [NSData dataWithContentsOfFile:cannedItemPath]; + cannedItem = [NSJSONSerialization JSONObjectWithData:cannedItemData options:0 error:nil]; + }); + _cannedItem = cannedItem; + } + return _cannedItem; +} + @end diff --git a/README.md b/README.md index 26fda71..7239bd3 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,9 @@ Register your application by following [these](https://dev.onedrive.com/app-regi * You can set your application Id and scopes directly on the ODClient object. -* Call the class method `[ODClient setMicrosoftAccountAppId: scopes:]` with a specified and . For more info about scopes, see [Authentication scopes](https://dev.onedrive.com/auth/msa_oauth.htm#authentication-scopes). +* For applications targeting OneDrive call the class method `[ODClient setMicrosoftAccountAppId: scopes:]` with a specified `` and ``. For more info about scopes, see [Authentication scopes](https://dev.onedrive.com/auth/msa_oauth.htm#authentication-scopes). + +* For applications targeting OneDrive for Business call the class method `[ODClient setActiveDirectoryAppId: redirectURL:]` with specified `` and ``. Note: the redirect URL must match the redirect URL that you specified in the [Azure Management Portal](https://manage.windowsazure.com/). ### 2.3 Getting an authenticated ODClient object @@ -94,7 +96,7 @@ Register your application by following [these](https://dev.onedrive.com/app-regi * Get an authenticated ODClient via the clientWithCompletion method: ```objc -ODClient *odClient = [ODClient clientWithCompletion:^(ODClient *client, NSError *error){ +[ODClient clientWithCompletion:^(ODClient *client, NSError *error){ if (!error){ self.odClient = client; }