Skip to content

Implement ParseAuthenticationManager #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 9, 2015
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 @@ -18,7 +18,7 @@
* An authentication provider that generates a random UUID that will be used as
* a key to identify this anonymous user until the user has been claimed.
*/
/** package */ class AnonymousAuthenticationProvider extends ParseAuthenticationProvider {
/** package */ class AnonymousAuthenticationProvider implements ParseAuthenticationProvider {

@Override
public Task<Map<String, String>> authenticateAsync() {
Expand All @@ -32,8 +32,9 @@ public Map<String, String> getAuthData() {
}

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

@Override
Expand Down
10 changes: 7 additions & 3 deletions Parse/src/main/java/com/parse/CachedCurrentUserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public Task<Void> setAsync(final ParseUser user) {
public Task<Void> then(Task<Void> toAwait) throws Exception {
return toAwait.continueWithTask(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(Task<Void> ignored) throws Exception {
public Task<Void> then(Task<Void> task) throws Exception {
ParseUser oldCurrentUser;
synchronized (mutex) {
oldCurrentUser = currentUser;
Expand All @@ -55,9 +55,13 @@ public Task<Void> then(Task<Void> ignored) throws Exception {
if (oldCurrentUser != null && oldCurrentUser != user) {
// We don't need to revoke the token since we're not explicitly calling logOut
// We don't need to remove persisted files since we're overwriting them
oldCurrentUser.logOutInternal();
return oldCurrentUser.logOutAsync(false);
}

return task;
}
}).continueWithTask(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(Task<Void> task) throws Exception {
synchronized (user.mutex) {
user.setIsCurrentUser(true);
user.synchronizeAllAuthData();
Expand Down
11 changes: 10 additions & 1 deletion Parse/src/main/java/com/parse/ParseAnonymousUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
*/
package com.parse;

import java.util.Map;

import bolts.Continuation;
import bolts.Task;

/**
Expand Down Expand Up @@ -62,7 +65,13 @@ public static boolean isLinked(ParseUser user) {
* @return A Task that will be resolved when logging in is completed.
*/
public static Task<ParseUser> logInInBackground() {
return getProvider().logInAsync();
final ParseAuthenticationProvider 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());
}
});
}

/**
Expand Down
77 changes: 77 additions & 0 deletions Parse/src/main/java/com/parse/ParseAuthenticationManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.parse;

import java.util.HashMap;
import java.util.Map;

import bolts.Continuation;
import bolts.Task;

/*** package */ class ParseAuthenticationManager {

private final Object lock = new Object();
private final Map<String, ParseAuthenticationProvider> authenticationProviders = new HashMap<>();
private final ParseCurrentUserController controller;

public ParseAuthenticationManager(ParseCurrentUserController controller) {
this.controller = controller;
}

public void register(ParseAuthenticationProvider provider) {
final String authType = provider.getAuthType();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add an exception around authType should not be nil?

if (authType == null) {
throw new IllegalArgumentException("Invalid authType: " + null);
}

synchronized (lock) {
if (authenticationProviders.containsKey(authType)) {
throw new IllegalStateException("Another " + authType + " provider was already registered: "
+ authenticationProviders.get(authType));
}
authenticationProviders.put(provider.getAuthType(), provider);
}

if (provider instanceof AnonymousAuthenticationProvider) {
// There's nothing to synchronize
return;
}

// Synchronize the current user with the auth provider.
controller.getAsync(false).onSuccess(new Continuation<ParseUser, Void>() {
@Override
public Void then(Task<ParseUser> task) throws Exception {
ParseUser user = task.getResult();
if (user != null) {
user.synchronizeAuthData(authType);
}
return null;
}
});
}

public boolean restoreAuthentication(String authType, Map<String, String> authData) {
ParseAuthenticationProvider provider;
synchronized (lock) {
provider = authenticationProviders.get(authType);
}
return provider == null || provider.restoreAuthentication(authData);
}

public Task<Void> deauthenticateAsync(String authType) {
ParseAuthenticationProvider provider;
synchronized (lock) {
provider = authenticationProviders.get(authType);
}
if (provider != null) {
return provider.deauthenticateAsync();
}
return Task.forResult(null);
}
}
41 changes: 5 additions & 36 deletions Parse/src/main/java/com/parse/ParseAuthenticationProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,32 @@

import java.util.Map;

import bolts.Continuation;
import bolts.Task;

/**
* Provides a general interface for delegation of the authentication process.
*/
/** package */ abstract class ParseAuthenticationProvider {
/** package */ interface ParseAuthenticationProvider {

/**
* Provides a unique name for the type of authentication the provider does.
* For example, the FacebookAuthenticationProvider would return "facebook".
*/
public abstract String getAuthType();
String getAuthType();

/**
* Begins the authentication process and invokes onSuccess() or onError() on
* the callback upon completion. This call should not block.
*
* @return A task that will be resolved upon the completion of authentication.
*/
public abstract Task<Map<String, String>> authenticateAsync();
Task<Map<String, String>> authenticateAsync();

/**
* Deauthenticates (logs out) the user associated with this provider. This
* call may block.
*/
public abstract void deauthenticate();
Task<Void> deauthenticateAsync();

/**
* Restores authentication that has been serialized, such as session keys,
Expand All @@ -49,35 +48,5 @@
* value indicates that the user should no longer be associated
* because of bad auth data.
*/
public abstract boolean restoreAuthentication(Map<String, String> authData);

public Task<ParseUser> logInAsync() {
return authenticateAsync().onSuccessTask(new Continuation<Map<String, String>, Task<ParseUser>>() {
@Override
public Task<ParseUser> then(Task<Map<String, String>> task) throws Exception {
return logInAsync(task.getResult());
}
});
}

public Task<ParseUser> logInAsync(Map<String, String> authData) {
return ParseUser.logInWithAsync(getAuthType(), authData);
}

public Task<Void> linkAsync(final ParseUser user) {
return authenticateAsync().onSuccessTask(new Continuation<Map<String, String>, Task<Void>>() {
@Override
public Task<Void> then(Task<Map<String, String>> task) throws Exception {
return linkAsync(user, task.getResult());
}
});
}

public Task<Void> linkAsync(ParseUser user, Map<String, String> authData) {
return user.linkWithAsync(getAuthType(), authData, user.getSessionToken());
}

public Task<Void> unlinkAsync(ParseUser user) {
return user.unlinkFromAsync(getAuthType());
}
boolean restoreAuthentication(Map<String, String> authData);
}
22 changes: 22 additions & 0 deletions Parse/src/main/java/com/parse/ParseCorePlugins.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public static ParseCorePlugins getInstance() {
private AtomicReference<ParseCurrentInstallationController> currentInstallationController =
new AtomicReference<>();

private AtomicReference<ParseAuthenticationManager> authenticationController =
new AtomicReference<>();

private AtomicReference<ParseQueryController> queryController = new AtomicReference<>();
private AtomicReference<ParseFileController> fileController = new AtomicReference<>();
private AtomicReference<ParseAnalyticsController> analyticsController = new AtomicReference<>();
Expand All @@ -59,6 +62,8 @@ private ParseCorePlugins() {
currentUserController.set(null);
currentInstallationController.set(null);

authenticationController.set(null);

queryController.set(null);
fileController.set(null);
analyticsController.set(null);
Expand Down Expand Up @@ -285,6 +290,23 @@ public void registerCurrentInstallationController(ParseCurrentInstallationContro
}
}

public ParseAuthenticationManager getAuthenticationManager() {
if (authenticationController.get() == null) {
ParseAuthenticationManager controller =
new ParseAuthenticationManager(getCurrentUserController());
authenticationController.compareAndSet(null, controller);
}
return authenticationController.get();
}

public void registerAuthenticationManager(ParseAuthenticationManager manager) {
if (!authenticationController.compareAndSet(null, manager)) {
throw new IllegalStateException(
"Another authentication manager was already registered: " +
authenticationController.get());
}
}

public ParseDefaultACLController getDefaultACLController() {
if (defaultACLController.get() == null) {
ParseDefaultACLController controller = new ParseDefaultACLController();
Expand Down
Loading