Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
*/
/** package */ class AnonymousAuthenticationProvider implements ParseAuthenticationProvider {

@Override
public Task<Map<String, String>> authenticateAsync() {
return Task.forResult(getAuthData());
}
Expand All @@ -32,14 +31,14 @@ public Map<String, String> getAuthData() {
}

@Override
public Task<Void> deauthenticateAsync() {
public Task<Void> deauthenticateInBackground() {
// do nothing
return Task.forResult(null);
}

@Override
public Task<Boolean> restoreAuthenticationAsync(Map<String, String> authData) {
return Task.forResult(true);
public Task<Void> restoreAuthenticationInBackground(Map<String, String> authData) {
return Task.forResult(null);
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions Parse/src/main/java/com/parse/ParseAnonymousUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ public static boolean isLinked(ParseUser user) {
* @return A Task that will be resolved when logging in is completed.
*/
public static Task<ParseUser> logInInBackground() {
final ParseAuthenticationProvider provider = getProvider();
final AnonymousAuthenticationProvider provider = getProvider();
return provider.authenticateAsync().onSuccessTask(new Continuation<Map<String, String>, Task<ParseUser>>() {
@Override
public Task<ParseUser> then(Task<Map<String, String>> task) throws Exception {
return ParseUser.logInWithAsync(provider.getAuthType(), task.getResult());
return ParseUser.logInWithInBackground(provider.getAuthType(), task.getResult());
}
});
}
Expand Down
8 changes: 4 additions & 4 deletions Parse/src/main/java/com/parse/ParseAuthenticationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ public Task<Void> then(Task<ParseUser> task) throws Exception {
});
}

public Task<Boolean> restoreAuthenticationAsync(String authType, Map<String, String> authData) {
public Task<Void> restoreAuthenticationAsync(String authType, Map<String, String> authData) {
ParseAuthenticationProvider provider;
synchronized (lock) {
provider = authenticationProviders.get(authType);
}
if (provider == null) {
return Task.forResult(true);
return Task.forResult(null);
}
return provider.restoreAuthenticationAsync(authData);
return provider.restoreAuthenticationInBackground(authData);
}

public Task<Void> deauthenticateAsync(String authType) {
Expand All @@ -73,7 +73,7 @@ public Task<Void> deauthenticateAsync(String authType) {
provider = authenticationProviders.get(authType);
}
if (provider != null) {
return provider.deauthenticateAsync();
return provider.deauthenticateInBackground();
}
return Task.forResult(null);
}
Expand Down
29 changes: 11 additions & 18 deletions Parse/src/main/java/com/parse/ParseAuthenticationProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,34 @@
import bolts.Task;

/**
* Provides a general interface for delegation of the authentication process.
* Provides a general interface for delegation of third party authentication.
*/
/** package */ interface ParseAuthenticationProvider {
public interface ParseAuthenticationProvider {

/**
* Provides a unique name for the type of authentication the provider does.
* For example, the FacebookAuthenticationProvider would return "facebook".
* @return A unique name for the type of authentication the provider does.
* <p />
* For example, the {@code FacebookAuthenticationProvider} would return {@code "facebook"}.
*/
String getAuthType();

/**
* Authenticates with the service.
* Deauthenticates (logs out) the user associated with this provider.
*
* @return A {@code Task} that will be resolved when authentication is complete.
* @return A {@link Task} that resolves when deauthentication completes.
*/
Task<Map<String, String>> authenticateAsync();
Task<Void> deauthenticateInBackground();

/**
* Deauthenticates (logs out) the user associated with this provider. This call may block.
*
* @return A {@link Task} that resolves when deauthentication is complete.
*/
Task<Void> deauthenticateAsync();

/**
* Restores authentication that has been serialized, such as session keys,
* etc.
* Restores authentication that has been serialized, such as session keys, etc.
*
* @param authData
* the auth data for the provider. This value may be null when
* The auth data for the provider. This value may be {@code null} when
* unlinking an account.
*
* @return A {@link Task} that resolves to {@code true} iff the {@code authData} was successfully
* synchronized or {@code false} if user should no longer be associated because of bad
* {@code authData}.
*/
Task<Boolean> restoreAuthenticationAsync(Map<String, String> authData);
Task<Void> restoreAuthenticationInBackground(Map<String, String> authData);
}
230 changes: 143 additions & 87 deletions Parse/src/main/java/com/parse/ParseUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -1078,80 +1078,33 @@ public ParseUser fetchIfNeeded() throws ParseException {

//region Third party authentication

/* package */ boolean isLinked(String authType) {
Map<String, Map<String, String>> authData = getAuthData();
return authData.containsKey(authType) && authData.get(authType) != null;
}

/**
* Ensures that all auth providers have auth data (e.g. access tokens, etc.) that matches this
* user.
* Registers a third party authentication provider.
* <p />
* <strong>Note: This shouldn't be called directly unless developing a third party authentication
* provider.</strong>
*
* @param provider The third party authentication provider to be registered.
*
* @see ParseAuthenticationProvider
*/
/* package */ Task<Void> synchronizeAllAuthDataAsync() {
Map<String, Map<String, String>> authData;
synchronized (mutex) {
if (!isCurrentUser()) {
return Task.forResult(null);
}
authData = getAuthData();
}
List<Task<Void>> tasks = new ArrayList<>(authData.size());
for (String authType : authData.keySet()) {
tasks.add(synchronizeAuthDataAsync(authType));
}
return Task.whenAll(tasks);
}

/* package */ Task<Void> synchronizeAuthDataAsync(String authType) {
Map<String, String> authData;
synchronized (mutex) {
if (!isCurrentUser()) {
return Task.forResult(null);
}
authData = getAuthData(authType);
}
return synchronizeAuthDataAsync(getAuthenticationManager(), authType, authData);
}

private Task<Void> synchronizeAuthDataAsync(
ParseAuthenticationManager manager, final String authType, Map<String, String> authData) {
return manager.restoreAuthenticationAsync(authType, authData).onSuccessTask(new Continuation<Boolean, Task<Void>>() {
@Override
public Task<Void> then(Task<Boolean> task) throws Exception {
boolean success = task.getResult();
if (!success) {
return unlinkFromAsync(authType);
}
return task.makeVoid();
}
});
}

/* package */ Task<Void> unlinkFromAsync(final String authType) {
synchronized (mutex) {
if (authType == null) {
return Task.forResult(null);
}
return Task.<Void> forResult(null).continueWithTask(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(Task<Void> task) throws Exception {
synchronized (mutex) {
if (getAuthData().containsKey(authType)) {
putAuthData(authType, null);
return saveInBackground();
}
return Task.forResult(null);
}
}
});
}
}

/* package */ static void registerAuthenticationProvider(ParseAuthenticationProvider provider) {
public static void registerAuthenticationProvider(ParseAuthenticationProvider provider) {
getAuthenticationManager().register(provider);
}

/* package */ static Task<ParseUser> logInWithAsync(
/**
* Logs in a user with third party authentication credentials.
* <p />
* <strong>Note: This shouldn't be called directly unless developing a third party authentication
* provider.</strong>
*
* @param authType The name of the third party authentication provider.
* @param authData The user credentials of the third party authentication provider.
* @return A {@code Task} is resolved when logging in completes.
*
* @see ParseAuthenticationProvider
*/
public static Task<ParseUser> logInWithInBackground(
final String authType, final Map<String, String> authData) {
if (authType == null) {
throw new IllegalArgumentException("Invalid authType: " + null);
Expand Down Expand Up @@ -1223,24 +1176,25 @@ public Task<ParseUser> then(Task<Void> task) throws Exception {
// Try to link the current user with third party user, unless a user is already linked
// to that third party user, then we'll just create a new user and link it with the
// third party user. New users will not be linked to the previous user's data.
return user.linkWithAsync(authType, authData).continueWithTask(new Continuation<Void, Task<ParseUser>>() {
@Override
public Task<ParseUser> then(Task<Void> task) throws Exception {
if (task.isFaulted()) {
Exception error = task.getError();
if (error instanceof ParseException
&& ((ParseException) error).getCode() == ParseException.ACCOUNT_ALREADY_LINKED) {
// An account that's linked to the given authData already exists, so log in
// instead of trying to claim.
return Task.<Void>forResult(null).continueWithTask(logInWithTask);
return user.linkWithInBackground(authType, authData)
.continueWithTask(new Continuation<Void, Task<ParseUser>>() {
@Override
public Task<ParseUser> then(Task<Void> task) throws Exception {
if (task.isFaulted()) {
Exception error = task.getError();
if (error instanceof ParseException
&& ((ParseException) error).getCode() == ParseException.ACCOUNT_ALREADY_LINKED) {
// An account that's linked to the given authData already exists, so log in
// instead of trying to claim.
return Task.<Void>forResult(null).continueWithTask(logInWithTask);
}
}
if (task.isCancelled()) {
return Task.cancelled();
}
return Task.forResult(user);
}
}
if (task.isCancelled()) {
return Task.cancelled();
}
return Task.forResult(user);
}
});
});
}
}
}
Expand All @@ -1250,6 +1204,65 @@ public Task<ParseUser> then(Task<Void> task) throws Exception {
});
}

/**
* Indicates whether this user is linked with a third party authentication provider.
* <p />
* <strong>Note: This shouldn't be called directly unless developing a third party authentication
* provider.</strong>
*
* @param authType The name of the third party authentication provider.
* @return {@code true} if linked, otherwise {@code false}.
*
* @see ParseAuthenticationProvider
*/
public boolean isLinked(String authType) {
Map<String, Map<String, String>> authData = getAuthData();
return authData.containsKey(authType) && authData.get(authType) != null;
}

/**
* Ensures that all auth providers have auth data (e.g. access tokens, etc.) that matches this
* user.
*/
/* package */ Task<Void> synchronizeAllAuthDataAsync() {
Map<String, Map<String, String>> authData;
synchronized (mutex) {
if (!isCurrentUser()) {
return Task.forResult(null);
}
authData = getAuthData();
}
List<Task<Void>> tasks = new ArrayList<>(authData.size());
for (String authType : authData.keySet()) {
tasks.add(synchronizeAuthDataAsync(authType));
}
return Task.whenAll(tasks);
}

/* package */ Task<Void> synchronizeAuthDataAsync(String authType) {
Map<String, String> authData;
synchronized (mutex) {
if (!isCurrentUser()) {
return Task.forResult(null);
}
authData = getAuthData(authType);
}
return synchronizeAuthDataAsync(getAuthenticationManager(), authType, authData);
}

private Task<Void> synchronizeAuthDataAsync(
ParseAuthenticationManager manager, final String authType, Map<String, String> authData) {
return manager.restoreAuthenticationAsync(authType, authData).continueWithTask(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(Task<Void> task) throws Exception {
if (task.isFaulted()) {
return unlinkFromInBackground(authType);
}
return task;
}
});
}

private Task<Void> linkWithAsync(
final String authType,
final Map<String, String> authData,
Expand Down Expand Up @@ -1289,14 +1302,57 @@ public Task<Void> then(Task<Void> task) throws Exception {
});
}

/* package */ Task<Void> linkWithAsync(
/**
* Links this user to a third party authentication provider.
* <p />
* <strong>Note: This shouldn't be called directly unless developing a third party authentication
* provider.</strong>
*
* @param authType The name of the third party authentication provider.
* @param authData The user credentials of the third party authentication provider.
* @return A {@code Task} is resolved when linking completes.
*
* @see ParseAuthenticationProvider
*/
public Task<Void> linkWithInBackground(
String authType, Map<String, String> authData) {
if (authType == null) {
throw new IllegalArgumentException("Invalid authType: " + null);
}
return linkWithAsync(authType, authData, getSessionToken());
}

/**
* Unlinks this user from a third party authentication provider.
* <p />
* <strong>Note: This shouldn't be called directly unless developing a third party authentication
* provider.</strong>
*
* @param authType The name of the third party authentication provider.
* @return A {@code Task} is resolved when unlinking completes.
*
* @see ParseAuthenticationProvider
*/
public Task<Void> unlinkFromInBackground(final String authType) {
synchronized (mutex) {
if (authType == null) {
return Task.forResult(null);
}
return Task.<Void> forResult(null).continueWithTask(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(Task<Void> task) throws Exception {
synchronized (mutex) {
if (getAuthData().containsKey(authType)) {
putAuthData(authType, null);
return saveInBackground();
}
return Task.forResult(null);
}
}
});
}
}

//endregion

/**
Expand Down
Loading