Skip to content

Commit 49d1a29

Browse files
committed
Merge pull request #77 from ParsePlatform/grantland.authentication_controller
Implement ParseAuthenticationManager
2 parents a2a1fd0 + 6bc204b commit 49d1a29

10 files changed

+308
-185
lines changed

Parse/src/main/java/com/parse/AnonymousAuthenticationProvider.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* An authentication provider that generates a random UUID that will be used as
1919
* a key to identify this anonymous user until the user has been claimed.
2020
*/
21-
/** package */ class AnonymousAuthenticationProvider extends ParseAuthenticationProvider {
21+
/** package */ class AnonymousAuthenticationProvider implements ParseAuthenticationProvider {
2222

2323
@Override
2424
public Task<Map<String, String>> authenticateAsync() {
@@ -32,8 +32,9 @@ public Map<String, String> getAuthData() {
3232
}
3333

3434
@Override
35-
public void deauthenticate() {
35+
public Task<Void> deauthenticateAsync() {
3636
// do nothing
37+
return Task.forResult(null);
3738
}
3839

3940
@Override

Parse/src/main/java/com/parse/CachedCurrentUserController.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public Task<Void> setAsync(final ParseUser user) {
4646
public Task<Void> then(Task<Void> toAwait) throws Exception {
4747
return toAwait.continueWithTask(new Continuation<Void, Task<Void>>() {
4848
@Override
49-
public Task<Void> then(Task<Void> ignored) throws Exception {
49+
public Task<Void> then(Task<Void> task) throws Exception {
5050
ParseUser oldCurrentUser;
5151
synchronized (mutex) {
5252
oldCurrentUser = currentUser;
@@ -55,9 +55,13 @@ public Task<Void> then(Task<Void> ignored) throws Exception {
5555
if (oldCurrentUser != null && oldCurrentUser != user) {
5656
// We don't need to revoke the token since we're not explicitly calling logOut
5757
// We don't need to remove persisted files since we're overwriting them
58-
oldCurrentUser.logOutInternal();
58+
return oldCurrentUser.logOutAsync(false);
5959
}
60-
60+
return task;
61+
}
62+
}).continueWithTask(new Continuation<Void, Task<Void>>() {
63+
@Override
64+
public Task<Void> then(Task<Void> task) throws Exception {
6165
synchronized (user.mutex) {
6266
user.setIsCurrentUser(true);
6367
user.synchronizeAllAuthData();

Parse/src/main/java/com/parse/ParseAnonymousUtils.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
*/
99
package com.parse;
1010

11+
import java.util.Map;
12+
13+
import bolts.Continuation;
1114
import bolts.Task;
1215

1316
/**
@@ -62,7 +65,13 @@ public static boolean isLinked(ParseUser user) {
6265
* @return A Task that will be resolved when logging in is completed.
6366
*/
6467
public static Task<ParseUser> logInInBackground() {
65-
return getProvider().logInAsync();
68+
final ParseAuthenticationProvider provider = getProvider();
69+
return provider.authenticateAsync().onSuccessTask(new Continuation<Map<String, String>, Task<ParseUser>>() {
70+
@Override
71+
public Task<ParseUser> then(Task<Map<String, String>> task) throws Exception {
72+
return ParseUser.logInWithAsync(provider.getAuthType(), task.getResult());
73+
}
74+
});
6675
}
6776

6877
/**
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) 2015-present, Parse, LLC.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
package com.parse;
10+
11+
import java.util.HashMap;
12+
import java.util.Map;
13+
14+
import bolts.Continuation;
15+
import bolts.Task;
16+
17+
/*** package */ class ParseAuthenticationManager {
18+
19+
private final Object lock = new Object();
20+
private final Map<String, ParseAuthenticationProvider> authenticationProviders = new HashMap<>();
21+
private final ParseCurrentUserController controller;
22+
23+
public ParseAuthenticationManager(ParseCurrentUserController controller) {
24+
this.controller = controller;
25+
}
26+
27+
public void register(ParseAuthenticationProvider provider) {
28+
final String authType = provider.getAuthType();
29+
if (authType == null) {
30+
throw new IllegalArgumentException("Invalid authType: " + null);
31+
}
32+
33+
synchronized (lock) {
34+
if (authenticationProviders.containsKey(authType)) {
35+
throw new IllegalStateException("Another " + authType + " provider was already registered: "
36+
+ authenticationProviders.get(authType));
37+
}
38+
authenticationProviders.put(provider.getAuthType(), provider);
39+
}
40+
41+
if (provider instanceof AnonymousAuthenticationProvider) {
42+
// There's nothing to synchronize
43+
return;
44+
}
45+
46+
// Synchronize the current user with the auth provider.
47+
controller.getAsync(false).onSuccess(new Continuation<ParseUser, Void>() {
48+
@Override
49+
public Void then(Task<ParseUser> task) throws Exception {
50+
ParseUser user = task.getResult();
51+
if (user != null) {
52+
user.synchronizeAuthData(authType);
53+
}
54+
return null;
55+
}
56+
});
57+
}
58+
59+
public boolean restoreAuthentication(String authType, Map<String, String> authData) {
60+
ParseAuthenticationProvider provider;
61+
synchronized (lock) {
62+
provider = authenticationProviders.get(authType);
63+
}
64+
return provider == null || provider.restoreAuthentication(authData);
65+
}
66+
67+
public Task<Void> deauthenticateAsync(String authType) {
68+
ParseAuthenticationProvider provider;
69+
synchronized (lock) {
70+
provider = authenticationProviders.get(authType);
71+
}
72+
if (provider != null) {
73+
return provider.deauthenticateAsync();
74+
}
75+
return Task.forResult(null);
76+
}
77+
}

Parse/src/main/java/com/parse/ParseAuthenticationProvider.java

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,32 @@
1010

1111
import java.util.Map;
1212

13-
import bolts.Continuation;
1413
import bolts.Task;
1514

1615
/**
1716
* Provides a general interface for delegation of the authentication process.
1817
*/
19-
/** package */ abstract class ParseAuthenticationProvider {
18+
/** package */ interface ParseAuthenticationProvider {
2019

2120
/**
2221
* Provides a unique name for the type of authentication the provider does.
2322
* For example, the FacebookAuthenticationProvider would return "facebook".
2423
*/
25-
public abstract String getAuthType();
24+
String getAuthType();
2625

2726
/**
2827
* Begins the authentication process and invokes onSuccess() or onError() on
2928
* the callback upon completion. This call should not block.
3029
*
3130
* @return A task that will be resolved upon the completion of authentication.
3231
*/
33-
public abstract Task<Map<String, String>> authenticateAsync();
32+
Task<Map<String, String>> authenticateAsync();
3433

3534
/**
3635
* Deauthenticates (logs out) the user associated with this provider. This
3736
* call may block.
3837
*/
39-
public abstract void deauthenticate();
38+
Task<Void> deauthenticateAsync();
4039

4140
/**
4241
* Restores authentication that has been serialized, such as session keys,
@@ -49,35 +48,5 @@
4948
* value indicates that the user should no longer be associated
5049
* because of bad auth data.
5150
*/
52-
public abstract boolean restoreAuthentication(Map<String, String> authData);
53-
54-
public Task<ParseUser> logInAsync() {
55-
return authenticateAsync().onSuccessTask(new Continuation<Map<String, String>, Task<ParseUser>>() {
56-
@Override
57-
public Task<ParseUser> then(Task<Map<String, String>> task) throws Exception {
58-
return logInAsync(task.getResult());
59-
}
60-
});
61-
}
62-
63-
public Task<ParseUser> logInAsync(Map<String, String> authData) {
64-
return ParseUser.logInWithAsync(getAuthType(), authData);
65-
}
66-
67-
public Task<Void> linkAsync(final ParseUser user) {
68-
return authenticateAsync().onSuccessTask(new Continuation<Map<String, String>, Task<Void>>() {
69-
@Override
70-
public Task<Void> then(Task<Map<String, String>> task) throws Exception {
71-
return linkAsync(user, task.getResult());
72-
}
73-
});
74-
}
75-
76-
public Task<Void> linkAsync(ParseUser user, Map<String, String> authData) {
77-
return user.linkWithAsync(getAuthType(), authData, user.getSessionToken());
78-
}
79-
80-
public Task<Void> unlinkAsync(ParseUser user) {
81-
return user.unlinkFromAsync(getAuthType());
82-
}
51+
boolean restoreAuthentication(Map<String, String> authData);
8352
}

Parse/src/main/java/com/parse/ParseCorePlugins.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public static ParseCorePlugins getInstance() {
3535
private AtomicReference<ParseCurrentInstallationController> currentInstallationController =
3636
new AtomicReference<>();
3737

38+
private AtomicReference<ParseAuthenticationManager> authenticationController =
39+
new AtomicReference<>();
40+
3841
private AtomicReference<ParseQueryController> queryController = new AtomicReference<>();
3942
private AtomicReference<ParseFileController> fileController = new AtomicReference<>();
4043
private AtomicReference<ParseAnalyticsController> analyticsController = new AtomicReference<>();
@@ -59,6 +62,8 @@ private ParseCorePlugins() {
5962
currentUserController.set(null);
6063
currentInstallationController.set(null);
6164

65+
authenticationController.set(null);
66+
6267
queryController.set(null);
6368
fileController.set(null);
6469
analyticsController.set(null);
@@ -285,6 +290,23 @@ public void registerCurrentInstallationController(ParseCurrentInstallationContro
285290
}
286291
}
287292

293+
public ParseAuthenticationManager getAuthenticationManager() {
294+
if (authenticationController.get() == null) {
295+
ParseAuthenticationManager controller =
296+
new ParseAuthenticationManager(getCurrentUserController());
297+
authenticationController.compareAndSet(null, controller);
298+
}
299+
return authenticationController.get();
300+
}
301+
302+
public void registerAuthenticationManager(ParseAuthenticationManager manager) {
303+
if (!authenticationController.compareAndSet(null, manager)) {
304+
throw new IllegalStateException(
305+
"Another authentication manager was already registered: " +
306+
authenticationController.get());
307+
}
308+
}
309+
288310
public ParseDefaultACLController getDefaultACLController() {
289311
if (defaultACLController.get() == null) {
290312
ParseDefaultACLController controller = new ParseDefaultACLController();

0 commit comments

Comments
 (0)