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

Commit 3378fa3

Browse files
zadrnlutsenko
authored andcommitted
Add support for using PF_Twitter without a linking or logging into a Parse account (#27)
1 parent f921eb1 commit 3378fa3

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

ParseTwitterUtils/PF_Twitter.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ NS_ASSUME_NONNULL_BEGIN
2121
*/
2222
@interface PF_Twitter : NSObject
2323

24+
/**
25+
Initializes an instance of `PF_Twitter` configured to access device Twitter accounts with Accounts.framework,
26+
and remote access to Twitter accounts - and, if no accounts are found locally - through a built-in webview.
27+
28+
After setting `consumerKey` and `consumerSecret`, authorization to Twitter accounts can be requested with
29+
`authorizeInBackground`, and then revoked with its opposite, `deauthorizeInBackground`.
30+
*/
31+
- (instancetype)init;
32+
2433
/**
2534
Consumer key of the application that is used to authorize with Twitter.
2635
*/
@@ -59,6 +68,14 @@ NS_ASSUME_NONNULL_BEGIN
5968
*/
6069
- (BFTask *)authorizeInBackground;
6170

71+
/**
72+
Invalidates an OAuth token for the current user, if the Twitter user has granted permission to the
73+
current application.
74+
75+
@return The task, that encapsulates the work being done.
76+
*/
77+
- (BFTask *)deauthorizeInBackground;
78+
6279
/**
6380
Displays an auth dialog and populates the authToken, authTokenSecret, userId, and screenName properties
6481
if the Twitter user grants permission to the application.

ParseTwitterUtils/PF_Twitter.m

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,28 @@ - (BFTask *)authorizeInBackground {
9292
return source.task;
9393
}];
9494
}
95+
- (BFTask *)deauthorizeInBackground {
96+
if (self.consumerKey.length == 0 || self.consumerSecret.length == 0) {
97+
//TODO: (nlutsenko) This doesn't look right, maybe we should add additional error code?
98+
return [BFTask taskWithError:[NSError errorWithDomain:PFParseErrorDomain code:1 userInfo:nil]];
99+
}
100+
101+
return [[self _performDeauthAsync] pftw_continueAsyncWithBlock:^id(BFTask *task) {
102+
BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource];
103+
if (task.cancelled) {
104+
[source cancel];
105+
} else if (!task.error && !task.result) {
106+
source.result = nil;
107+
} else if (task.error) {
108+
[source trySetError:task.error];
109+
} else if (task.result) {
110+
[self setLoginResultValues:nil];
111+
112+
[source trySetResult:task.result];
113+
}
114+
return source.task;
115+
}];
116+
}
95117

96118
- (void)authorizeWithSuccess:(void (^)(void))success
97119
failure:(void (^)(NSError *error))failure
@@ -428,6 +450,26 @@ - (BFTask *)_performWebViewAuthAsync {
428450
return source.task;
429451
}
430452

453+
- (BFTask *)_performDeauthAsync {
454+
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
455+
request.URL = [NSURL URLWithString:@"https://api.twitter.com/oauth2/invalidate_token"];
456+
request.HTTPMethod = @"POST";
457+
458+
[self signRequest:request];
459+
460+
BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];
461+
462+
[[self.urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
463+
if (error) {
464+
[taskCompletionSource trySetError:error];
465+
} else {
466+
[taskCompletionSource trySetResult:data];
467+
}
468+
}] resume];
469+
470+
return taskCompletionSource.task;
471+
}
472+
431473
///--------------------------------------
432474
#pragma mark - Sign Request
433475
///--------------------------------------

Tests/Unit/TwitterTests.m

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,4 +622,64 @@ - (void)testAuthorizeWithoutLocalAccountAndNetworkSuccess {
622622
OCMVerifyAll(mockedURLSession);
623623
}
624624

625+
- (void)testDeauthorizeLoggedOutAccount {
626+
id store = PFStrictClassMock([ACAccountStore class]);
627+
NSURLSession *session = PFStrictClassMock([NSURLSession class]);
628+
id mockedDialog = PFStrictProtocolMock(@protocol(PFOAuth1FlowDialogInterface));
629+
PF_Twitter *twitter = [[PF_Twitter alloc] initWithAccountStore:store urlSession:session dialogClass:mockedDialog];
630+
631+
XCTestExpectation *expectation = [self currentSelectorTestExpectation];
632+
[[twitter authorizeInBackground] continueWithBlock:^id(BFTask *task) {
633+
NSError *error = task.error;
634+
XCTAssertNotNil(error);
635+
XCTAssertEqualObjects(error.domain, PFParseErrorDomain);
636+
XCTAssertEqual(error.code, 1);
637+
[expectation fulfill];
638+
return nil;
639+
}];
640+
[self waitForTestExpectations];
641+
}
642+
643+
- (void)testDeauthorizeLoggedInAccount {
644+
id mockedStore = PFStrictClassMock([ACAccountStore class]);
645+
id mockedURLSession = PFStrictClassMock([NSURLSession class]);
646+
id mockedOperationQueue = PFStrictClassMock([NSOperationQueue class]);
647+
648+
id mockedDialog = PFStrictProtocolMock(@protocol(PFOAuth1FlowDialogInterface));
649+
PF_Twitter *twitter = [[PF_Twitter alloc] initWithAccountStore:mockedStore urlSession:mockedURLSession dialogClass:mockedDialog];
650+
twitter.consumerKey = @"consumer_key";
651+
twitter.consumerSecret = @"consumer_secret";
652+
twitter.authToken = @"auth_token";
653+
twitter.authTokenSecret = @"auth_token_secret";
654+
twitter.userId = @"user_id";
655+
twitter.screenName = @"screen_name";
656+
657+
__block NSURLSessionDataTaskCompletionHandler completionHandler = nil;
658+
[OCMStub([mockedURLSession dataTaskWithRequest:[OCMArg checkWithBlock:^BOOL(id obj) {
659+
NSURLRequest *request = obj;
660+
return [request.URL.lastPathComponent isEqualToString:@"invalidate_token"];
661+
}] completionHandler:[OCMArg checkWithBlock:^BOOL(id obj) {
662+
completionHandler = obj;
663+
return (obj != nil);
664+
}]]).andDo(^(NSInvocation *invocation) {
665+
completionHandler([NSData data], nil, nil);
666+
}) andReturn:[OCMockObject niceMockForClass:[NSURLSessionDataTask class]]];
667+
668+
XCTestExpectation *expectation = [self currentSelectorTestExpectation];
669+
[[twitter deauthorizeInBackground] continueWithBlock:^id(BFTask *task) {
670+
NSError *error = task.error;
671+
XCTAssertNil(error);
672+
XCTAssertNotNil(task.result);
673+
674+
XCTAssertNil(twitter.authToken);
675+
XCTAssertNil(twitter.authTokenSecret);
676+
XCTAssertNil(twitter.userId);
677+
XCTAssertNil(twitter.screenName);
678+
679+
[expectation fulfill];
680+
return nil;
681+
}];
682+
[self waitForTestExpectations];
683+
}
684+
625685
@end

0 commit comments

Comments
 (0)