From f0eda12d780c7a1dc1bf0775c1b42aa8be286d06 Mon Sep 17 00:00:00 2001 From: Grantland Chew Date: Fri, 11 Sep 2015 15:07:44 -0700 Subject: [PATCH 1/3] Clean up third party authentication APIs * ParseAuthenticationProvider -> ParseAuthenticationCallbacks * ParseAuthenticationCallback APIs are synchronous, but executed on bg thread to simplify usage * ParseAuthenticationCallback APIs are named more callback-y * ParseUser.registerAuthenticationCallbacks(authType, callback) <- now takes "authType" to match rest of APIs --- .../AnonymousAuthenticationProvider.java | 48 ------------- .../parse/CachedCurrentUserController.java | 6 +- .../java/com/parse/ParseAnonymousUtils.java | 26 +++---- .../parse/ParseAuthenticationCallbacks.java | 39 +++++++++++ .../com/parse/ParseAuthenticationManager.java | 49 +++++++------ .../parse/ParseAuthenticationProvider.java | 46 ------------- Parse/src/main/java/com/parse/ParseUser.java | 68 ++++++++++--------- .../parse/ParseAuthenticationManagerTest.java | 32 ++++----- .../test/java/com/parse/ParseUserTest.java | 41 ++++++----- 9 files changed, 147 insertions(+), 208 deletions(-) delete mode 100644 Parse/src/main/java/com/parse/AnonymousAuthenticationProvider.java create mode 100644 Parse/src/main/java/com/parse/ParseAuthenticationCallbacks.java delete mode 100644 Parse/src/main/java/com/parse/ParseAuthenticationProvider.java diff --git a/Parse/src/main/java/com/parse/AnonymousAuthenticationProvider.java b/Parse/src/main/java/com/parse/AnonymousAuthenticationProvider.java deleted file mode 100644 index 172509b90..000000000 --- a/Parse/src/main/java/com/parse/AnonymousAuthenticationProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 java.util.UUID; - -import bolts.Task; - -/** - * 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 implements ParseAuthenticationProvider { - - public Task> authenticateAsync() { - return Task.forResult(getAuthData()); - } - - public Map getAuthData() { - Map authData = new HashMap<>(); - authData.put("id", UUID.randomUUID().toString()); - return authData; - } - - @Override - public Task deauthenticateInBackground() { - // do nothing - return Task.forResult(null); - } - - @Override - public Task restoreAuthenticationInBackground(Map authData) { - return Task.forResult(null); - } - - @Override - public String getAuthType() { - return ParseAnonymousUtils.AUTH_TYPE; - } -} diff --git a/Parse/src/main/java/com/parse/CachedCurrentUserController.java b/Parse/src/main/java/com/parse/CachedCurrentUserController.java index a5b4a8ccd..077de9e23 100644 --- a/Parse/src/main/java/com/parse/CachedCurrentUserController.java +++ b/Parse/src/main/java/com/parse/CachedCurrentUserController.java @@ -268,10 +268,8 @@ public ParseUser then(Task task) throws Exception { } private ParseUser lazyLogIn() { - AnonymousAuthenticationProvider provider = ParseAnonymousUtils.getProvider(); - String authType = provider.getAuthType(); - Map authData = provider.getAuthData(); - return lazyLogIn(authType, authData); + Map authData = ParseAnonymousUtils.getAuthData(); + return lazyLogIn(ParseAnonymousUtils.AUTH_TYPE, authData); } /* package for tests */ ParseUser lazyLogIn(String authType, Map authData) { diff --git a/Parse/src/main/java/com/parse/ParseAnonymousUtils.java b/Parse/src/main/java/com/parse/ParseAnonymousUtils.java index 657ff44e1..fc3482f23 100644 --- a/Parse/src/main/java/com/parse/ParseAnonymousUtils.java +++ b/Parse/src/main/java/com/parse/ParseAnonymousUtils.java @@ -8,7 +8,9 @@ */ package com.parse; +import java.util.HashMap; import java.util.Map; +import java.util.UUID; import bolts.Continuation; import bolts.Task; @@ -35,18 +37,8 @@ * */ public final class ParseAnonymousUtils { - private static AnonymousAuthenticationProvider provider; - /* package */ static final String AUTH_TYPE = "anonymous"; - /* package */ static AnonymousAuthenticationProvider getProvider() { - if (provider == null) { - provider = new AnonymousAuthenticationProvider(); - ParseUser.registerAuthenticationProvider(provider); - } - return provider; - } - /** * Whether the user is logged in anonymously. * @@ -65,13 +57,7 @@ public static boolean isLinked(ParseUser user) { * @return A Task that will be resolved when logging in is completed. */ public static Task logInInBackground() { - final AnonymousAuthenticationProvider provider = getProvider(); - return provider.authenticateAsync().onSuccessTask(new Continuation, Task>() { - @Override - public Task then(Task> task) throws Exception { - return ParseUser.logInWithInBackground(provider.getAuthType(), task.getResult()); - } - }); + return ParseUser.logInWithInBackground(AUTH_TYPE, getAuthData()); } /** @@ -84,6 +70,12 @@ public static void logIn(LogInCallback callback) { ParseTaskUtils.callbackOnMainThreadAsync(logInInBackground(), callback); } + /* package */ static Map getAuthData() { + Map authData = new HashMap<>(); + authData.put("id", UUID.randomUUID().toString()); + return authData; + } + private ParseAnonymousUtils() { // do nothing } diff --git a/Parse/src/main/java/com/parse/ParseAuthenticationCallbacks.java b/Parse/src/main/java/com/parse/ParseAuthenticationCallbacks.java new file mode 100644 index 000000000..289b5a3ac --- /dev/null +++ b/Parse/src/main/java/com/parse/ParseAuthenticationCallbacks.java @@ -0,0 +1,39 @@ +/* + * 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.Map; + +/** + * Provides a general interface for delegation of third party authentication callbacks. + */ +public interface ParseAuthenticationCallbacks { + /** + * Called when restoring third party authentication credentials that have been serialized, + * such as session keys, etc. + *

+ * Note: This will be executed in a background thread. + * + * @param authData + * The auth data for the provider. This value may be {@code null} when + * unlinking an account. + * + * @return {@code true} iff the {@code authData} was successfully synchronized or {@code false} + * if user should no longer be associated because of bad {@code authData}. + */ + boolean onRestoreAuthentication(Map authData); + + /** + * Called when deauthenticating (logging out) the user associated with this third party + * authentication source. + *

+ * Note: This will be executed in a background thread. + */ + void onDeauthenticate(); +} diff --git a/Parse/src/main/java/com/parse/ParseAuthenticationManager.java b/Parse/src/main/java/com/parse/ParseAuthenticationManager.java index bb71d96f2..9e8eee10e 100644 --- a/Parse/src/main/java/com/parse/ParseAuthenticationManager.java +++ b/Parse/src/main/java/com/parse/ParseAuthenticationManager.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Callable; import bolts.Continuation; import bolts.Task; @@ -17,33 +18,32 @@ /** package */ class ParseAuthenticationManager { private final Object lock = new Object(); - private final Map authenticationProviders = new HashMap<>(); + private final Map callbacks = new HashMap<>(); private final ParseCurrentUserController controller; public ParseAuthenticationManager(ParseCurrentUserController controller) { this.controller = controller; } - public void register(ParseAuthenticationProvider provider) { - final String authType = provider.getAuthType(); + public void register(final String authType, ParseAuthenticationCallbacks callbacks) { 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)); + if (this.callbacks.containsKey(authType)) { + throw new IllegalStateException("Callbacks already registered for <" + authType + ">: " + + this.callbacks.get(authType)); } - authenticationProviders.put(provider.getAuthType(), provider); + this.callbacks.put(authType, callbacks); } - if (provider instanceof AnonymousAuthenticationProvider) { + if (ParseAnonymousUtils.AUTH_TYPE.equals(authType)) { // There's nothing to synchronize return; } - // Synchronize the current user with the auth provider. + // Synchronize the current user with the auth callbacks. controller.getAsync(false).onSuccessTask(new Continuation>() { @Override public Task then(Task task) throws Exception { @@ -56,24 +56,35 @@ public Task then(Task task) throws Exception { }); } - public Task restoreAuthenticationAsync(String authType, Map authData) { - ParseAuthenticationProvider provider; + public Task restoreAuthenticationAsync(String authType, final Map authData) { + final ParseAuthenticationCallbacks callbacks; synchronized (lock) { - provider = authenticationProviders.get(authType); + callbacks = this.callbacks.get(authType); } - if (provider == null) { - return Task.forResult(null); + if (callbacks == null) { + return Task.forResult(true); } - return provider.restoreAuthenticationInBackground(authData); + return Task.call(new Callable() { + @Override + public Boolean call() throws Exception { + return callbacks.onRestoreAuthentication(authData); + } + }, ParseExecutors.io()); } public Task deauthenticateAsync(String authType) { - ParseAuthenticationProvider provider; + final ParseAuthenticationCallbacks callbacks; synchronized (lock) { - provider = authenticationProviders.get(authType); + callbacks = this.callbacks.get(authType); } - if (provider != null) { - return provider.deauthenticateInBackground(); + if (callbacks != null) { + return Task.call(new Callable() { + @Override + public Void call() throws Exception { + callbacks.onDeauthenticate(); + return null; + } + }, ParseExecutors.io()); } return Task.forResult(null); } diff --git a/Parse/src/main/java/com/parse/ParseAuthenticationProvider.java b/Parse/src/main/java/com/parse/ParseAuthenticationProvider.java deleted file mode 100644 index ecf6ba680..000000000 --- a/Parse/src/main/java/com/parse/ParseAuthenticationProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.Map; - -import bolts.Task; - -/** - * Provides a general interface for delegation of third party authentication. - */ -public interface ParseAuthenticationProvider { - - /** - * @return A unique name for the type of authentication the provider does. - *

- * For example, the {@code FacebookAuthenticationProvider} would return {@code "facebook"}. - */ - String getAuthType(); - - /** - * Deauthenticates (logs out) the user associated with this provider. - * - * @return A {@link Task} that resolves when deauthentication completes. - */ - Task deauthenticateInBackground(); - - /** - * Restores authentication that has been serialized, such as session keys, etc. - * - * @param authData - * 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 restoreAuthenticationInBackground(Map authData); -} diff --git a/Parse/src/main/java/com/parse/ParseUser.java b/Parse/src/main/java/com/parse/ParseUser.java index f8bc88466..b6997e446 100644 --- a/Parse/src/main/java/com/parse/ParseUser.java +++ b/Parse/src/main/java/com/parse/ParseUser.java @@ -1079,30 +1079,31 @@ public ParseUser fetchIfNeeded() throws ParseException { //region Third party authentication /** - * Registers a third party authentication provider. + * Registers third party authentication callbacks. *

- * Note: This shouldn't be called directly unless developing a third party authentication - * provider. + * Note: This shouldn't be called directly unless developing a third party authentication + * library. * - * @param provider The third party authentication provider to be registered. + * @param callbacks The third party authentication callbacks to be registered. * - * @see ParseAuthenticationProvider + * @see ParseAuthenticationCallbacks */ - public static void registerAuthenticationProvider(ParseAuthenticationProvider provider) { - getAuthenticationManager().register(provider); + public static void registerAuthenticationCallbacks( + String authType, ParseAuthenticationCallbacks callbacks) { + getAuthenticationManager().register(authType, callbacks); } /** * Logs in a user with third party authentication credentials. *

- * Note: This shouldn't be called directly unless developing a third party authentication - * provider. + * Note: This shouldn't be called directly unless developing a third party authentication + * library. * - * @param authType The name of the third party authentication provider. - * @param authData The user credentials of the third party authentication provider. + * @param authType The name of the third party authentication source. + * @param authData The user credentials of the third party authentication source. * @return A {@code Task} is resolved when logging in completes. * - * @see ParseAuthenticationProvider + * @see ParseAuthenticationCallbacks */ public static Task logInWithInBackground( final String authType, final Map authData) { @@ -1205,15 +1206,15 @@ public Task then(Task task) throws Exception { } /** - * Indicates whether this user is linked with a third party authentication provider. + * Indicates whether this user is linked with a third party authentication source. *

- * Note: This shouldn't be called directly unless developing a third party authentication - * provider. + * Note: This shouldn't be called directly unless developing a third party authentication + * library. * - * @param authType The name of the third party authentication provider. + * @param authType The name of the third party authentication source. * @return {@code true} if linked, otherwise {@code false}. * - * @see ParseAuthenticationProvider + * @see ParseAuthenticationCallbacks */ public boolean isLinked(String authType) { Map> authData = getAuthData(); @@ -1221,7 +1222,7 @@ public boolean isLinked(String authType) { } /** - * Ensures that all auth providers have auth data (e.g. access tokens, etc.) that matches this + * Ensures that all auth sources have auth data (e.g. access tokens, etc.) that matches this * user. */ /* package */ Task synchronizeAllAuthDataAsync() { @@ -1252,13 +1253,14 @@ public boolean isLinked(String authType) { private Task synchronizeAuthDataAsync( ParseAuthenticationManager manager, final String authType, Map authData) { - return manager.restoreAuthenticationAsync(authType, authData).continueWithTask(new Continuation>() { + return manager.restoreAuthenticationAsync(authType, authData).continueWithTask(new Continuation>() { @Override - public Task then(Task task) throws Exception { - if (task.isFaulted()) { + public Task then(Task task) throws Exception { + boolean success = !task.isFaulted() && task.getResult(); + if (!success) { return unlinkFromInBackground(authType); } - return task; + return task.makeVoid(); } }); } @@ -1303,16 +1305,16 @@ public Task then(Task task) throws Exception { } /** - * Links this user to a third party authentication provider. + * Links this user to a third party authentication source. *

- * Note: This shouldn't be called directly unless developing a third party authentication - * provider. + * Note: This shouldn't be called directly unless developing a third party authentication + * library. * - * @param authType The name of the third party authentication provider. - * @param authData The user credentials of the third party authentication provider. + * @param authType The name of the third party authentication source. + * @param authData The user credentials of the third party authentication source. * @return A {@code Task} is resolved when linking completes. * - * @see ParseAuthenticationProvider + * @see ParseAuthenticationCallbacks */ public Task linkWithInBackground( String authType, Map authData) { @@ -1323,15 +1325,15 @@ public Task linkWithInBackground( } /** - * Unlinks this user from a third party authentication provider. + * Unlinks this user from a third party authentication source. *

- * Note: This shouldn't be called directly unless developing a third party authentication - * provider. + * Note: This shouldn't be called directly unless developing a third party authentication + * library. * - * @param authType The name of the third party authentication provider. + * @param authType The name of the third party authentication source. * @return A {@code Task} is resolved when unlinking completes. * - * @see ParseAuthenticationProvider + * @see ParseAuthenticationCallbacks */ public Task unlinkFromInBackground(final String authType) { synchronized (mutex) { diff --git a/Parse/src/test/java/com/parse/ParseAuthenticationManagerTest.java b/Parse/src/test/java/com/parse/ParseAuthenticationManagerTest.java index 47a82ab33..807207f2d 100644 --- a/Parse/src/test/java/com/parse/ParseAuthenticationManagerTest.java +++ b/Parse/src/test/java/com/parse/ParseAuthenticationManagerTest.java @@ -31,14 +31,13 @@ public class ParseAuthenticationManagerTest { private ParseAuthenticationManager manager; private ParseCurrentUserController controller; - private ParseAuthenticationProvider provider; + private ParseAuthenticationCallbacks provider; @Before public void setUp() { controller = mock(ParseCurrentUserController.class); manager = new ParseAuthenticationManager(controller); - provider = mock(ParseAuthenticationProvider.class); - when(provider.getAuthType()).thenReturn("test_provider"); + provider = mock(ParseAuthenticationCallbacks.class); } //region testRegister @@ -46,21 +45,17 @@ public void setUp() { @Test public void testRegisterMultipleShouldThrow() { when(controller.getAsync(false)).thenReturn(Task.forResult(null)); - ParseAuthenticationProvider provider2 = mock(ParseAuthenticationProvider.class); - when(provider2.getAuthType()).thenReturn("test_provider"); + ParseAuthenticationCallbacks provider2 = mock(ParseAuthenticationCallbacks.class); - manager.register(provider); + manager.register("test_provider", provider); thrown.expect(IllegalStateException.class); - manager.register(provider2); + manager.register("test_provider", provider2); } @Test public void testRegisterAnonymous() { - ParseAuthenticationProvider anonymous = mock(AnonymousAuthenticationProvider.class); - when(anonymous.getAuthType()).thenReturn("anonymous"); - - manager.register(anonymous); + manager.register("anonymous", mock(ParseAuthenticationCallbacks.class)); verifyNoMoreInteractions(controller); } @@ -69,7 +64,7 @@ public void testRegister() { ParseUser user = mock(ParseUser.class); when(controller.getAsync(false)).thenReturn(Task.forResult(user)); - manager.register(provider); + manager.register("test_provider", provider); verify(controller).getAsync(false); verify(user).synchronizeAuthDataAsync("test_provider"); } @@ -79,24 +74,23 @@ public void testRegister() { @Test public void testRestoreAuthentication() throws ParseException { when(controller.getAsync(false)).thenReturn(Task.forResult(null)); - when(provider.restoreAuthenticationInBackground(Matchers.>any())) - .thenReturn(Task.forResult(null)); - manager.register(provider); + when(provider.onRestoreAuthentication(Matchers.>any())) + .thenReturn(true); + manager.register("test_provider", provider); Map authData = new HashMap<>(); ParseTaskUtils.wait(manager.restoreAuthenticationAsync("test_provider", authData)); - verify(provider).restoreAuthenticationInBackground(authData); + verify(provider).onRestoreAuthentication(authData); } @Test public void testDeauthenticateAsync() throws ParseException { when(controller.getAsync(false)).thenReturn(Task.forResult(null)); - when(provider.deauthenticateInBackground()).thenReturn(Task.forResult(null)); - manager.register(provider); + manager.register("test_provider", provider); ParseTaskUtils.wait(manager.deauthenticateAsync("test_provider")); - verify(provider).deauthenticateInBackground(); + verify(provider).onDeauthenticate(); } } diff --git a/Parse/src/test/java/com/parse/ParseUserTest.java b/Parse/src/test/java/com/parse/ParseUserTest.java index fc9d37a5f..ad2a04f76 100644 --- a/Parse/src/test/java/com/parse/ParseUserTest.java +++ b/Parse/src/test/java/com/parse/ParseUserTest.java @@ -568,12 +568,11 @@ public void testlinkWithInBackgroundWithSaveAsyncSuccess() throws Exception { .thenReturn(Task.forResult(null)); when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); - // Register a mock authenticationProvider - ParseAuthenticationProvider provider = mock(ParseAuthenticationProvider.class); - when(provider.getAuthType()).thenReturn("facebook"); - when(provider.restoreAuthenticationInBackground(Matchers.>any())) - .thenReturn(Task.forResult(null)); - ParseUser.registerAuthenticationProvider(provider); + // Register mock callbacks + ParseAuthenticationCallbacks callbacks = mock(ParseAuthenticationCallbacks.class); + when(callbacks.onRestoreAuthentication(Matchers.>any())) + .thenReturn(true); + ParseUser.registerAuthenticationCallbacks("facebook", callbacks); ParseUser user = new ParseUser(); // To make synchronizeAuthData work @@ -591,7 +590,7 @@ public void testlinkWithInBackgroundWithSaveAsyncSuccess() throws Exception { Map authData = new HashMap<>(); authData.put("token", "test"); - ParseTaskUtils.wait(partialMockUser.linkWithInBackground(provider.getAuthType(), authData)); + ParseTaskUtils.wait(partialMockUser.linkWithInBackground("facebook", authData)); // Make sure we stripAnonymity assertNull(partialMockUser.getAuthData().get(ParseAnonymousUtils.AUTH_TYPE)); @@ -601,7 +600,7 @@ public void testlinkWithInBackgroundWithSaveAsyncSuccess() throws Exception { verify(partialMockUser, times(1)) .saveAsync(eq("sessionTokenAgain"), eq(false), Matchers.>any()); // Make sure synchronizeAuthData() is called - verify(provider, times(1)).restoreAuthenticationInBackground(authData); + verify(callbacks, times(1)).onRestoreAuthentication(authData); } @Test @@ -1289,12 +1288,11 @@ public void testSynchronizeAuthData() throws Exception { ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(currentUser)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); - // Register a mock authenticationProvider - ParseAuthenticationProvider provider = mock(ParseAuthenticationProvider.class); - when(provider.getAuthType()).thenReturn("facebook"); - when(provider.restoreAuthenticationInBackground(Matchers.>any())) - .thenReturn(Task.forResult(null)); - ParseUser.registerAuthenticationProvider(provider); + // Register mock callbacks + ParseAuthenticationCallbacks callbacks = mock(ParseAuthenticationCallbacks.class); + when(callbacks.onRestoreAuthentication(Matchers.>any())) + .thenReturn(true); + ParseUser.registerAuthenticationCallbacks("facebook", callbacks); // Set user initial state String authType = "facebook"; @@ -1309,7 +1307,7 @@ public void testSynchronizeAuthData() throws Exception { ParseTaskUtils.wait(user.synchronizeAuthDataAsync(authType)); // Make sure we restore authentication - verify(provider, times(1)).restoreAuthenticationInBackground(authData); + verify(callbacks, times(1)).onRestoreAuthentication(authData); } @Test @@ -1319,12 +1317,11 @@ public void testSynchronizeAllAuthData() throws Exception { ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(currentUser)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); - // Register a mock authenticationProvider - ParseAuthenticationProvider provider = mock(ParseAuthenticationProvider.class); - when(provider.getAuthType()).thenReturn("facebook"); - when(provider.restoreAuthenticationInBackground(Matchers.>any())) - .thenReturn(Task.forResult(null)); - ParseUser.registerAuthenticationProvider(provider); + // Register mock callbacks + ParseAuthenticationCallbacks callbacks = mock(ParseAuthenticationCallbacks.class); + when(callbacks.onRestoreAuthentication(Matchers.>any())) + .thenReturn(true); + ParseUser.registerAuthenticationCallbacks("facebook", callbacks); // Set user initial state String facebookAuthType = "facebook"; @@ -1339,7 +1336,7 @@ public void testSynchronizeAllAuthData() throws Exception { ParseTaskUtils.wait(user.synchronizeAllAuthDataAsync()); // Make sure we restore authentication - verify(provider, times(1)).restoreAuthenticationInBackground(facebookAuthData); + verify(callbacks, times(1)).onRestoreAuthentication(facebookAuthData); } //endregion From cf8b4dcbdbfbdef5024b475bc09f712bdb2999bc Mon Sep 17 00:00:00 2001 From: Grantland Chew Date: Fri, 11 Sep 2015 15:30:29 -0700 Subject: [PATCH 2/3] Clean up unecessarily complex code --- Parse/src/main/java/com/parse/ParseUser.java | 21 ++++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/Parse/src/main/java/com/parse/ParseUser.java b/Parse/src/main/java/com/parse/ParseUser.java index b6997e446..e66e226b6 100644 --- a/Parse/src/main/java/com/parse/ParseUser.java +++ b/Parse/src/main/java/com/parse/ParseUser.java @@ -1336,23 +1336,18 @@ public Task linkWithInBackground( * @see ParseAuthenticationCallbacks */ public Task unlinkFromInBackground(final String authType) { + if (authType == null) { + return Task.forResult(null); + } + synchronized (mutex) { - if (authType == null) { + if (!getAuthData().containsKey(authType)) { return Task.forResult(null); } - return Task. forResult(null).continueWithTask(new Continuation>() { - @Override - public Task then(Task task) throws Exception { - synchronized (mutex) { - if (getAuthData().containsKey(authType)) { - putAuthData(authType, null); - return saveInBackground(); - } - return Task.forResult(null); - } - } - }); + putAuthData(authType, null); } + + return saveInBackground(); } //endregion From 51ada3ec54149a80996b43f94d1532dbd22d9d75 Mon Sep 17 00:00:00 2001 From: Grantland Chew Date: Fri, 11 Sep 2015 16:12:37 -0700 Subject: [PATCH 3/3] Rename to AuthenticationCallback and onRestore --- ...backs.java => AuthenticationCallback.java} | 14 +++------- .../com/parse/ParseAuthenticationManager.java | 26 +++++++++---------- Parse/src/main/java/com/parse/ParseUser.java | 21 ++++++++------- .../parse/ParseAuthenticationManagerTest.java | 14 +++++----- .../test/java/com/parse/ParseUserTest.java | 24 ++++++++--------- 5 files changed, 46 insertions(+), 53 deletions(-) rename Parse/src/main/java/com/parse/{ParseAuthenticationCallbacks.java => AuthenticationCallback.java} (69%) diff --git a/Parse/src/main/java/com/parse/ParseAuthenticationCallbacks.java b/Parse/src/main/java/com/parse/AuthenticationCallback.java similarity index 69% rename from Parse/src/main/java/com/parse/ParseAuthenticationCallbacks.java rename to Parse/src/main/java/com/parse/AuthenticationCallback.java index 289b5a3ac..396a94e12 100644 --- a/Parse/src/main/java/com/parse/ParseAuthenticationCallbacks.java +++ b/Parse/src/main/java/com/parse/AuthenticationCallback.java @@ -13,12 +13,12 @@ /** * Provides a general interface for delegation of third party authentication callbacks. */ -public interface ParseAuthenticationCallbacks { +public interface AuthenticationCallback { /** * Called when restoring third party authentication credentials that have been serialized, * such as session keys, etc. *

- * Note: This will be executed in a background thread. + * Note: This will be executed on a background thread. * * @param authData * The auth data for the provider. This value may be {@code null} when @@ -27,13 +27,5 @@ public interface ParseAuthenticationCallbacks { * @return {@code true} iff the {@code authData} was successfully synchronized or {@code false} * if user should no longer be associated because of bad {@code authData}. */ - boolean onRestoreAuthentication(Map authData); - - /** - * Called when deauthenticating (logging out) the user associated with this third party - * authentication source. - *

- * Note: This will be executed in a background thread. - */ - void onDeauthenticate(); + boolean onRestore(Map authData); } diff --git a/Parse/src/main/java/com/parse/ParseAuthenticationManager.java b/Parse/src/main/java/com/parse/ParseAuthenticationManager.java index 9e8eee10e..636f2b7ca 100644 --- a/Parse/src/main/java/com/parse/ParseAuthenticationManager.java +++ b/Parse/src/main/java/com/parse/ParseAuthenticationManager.java @@ -18,24 +18,24 @@ /** package */ class ParseAuthenticationManager { private final Object lock = new Object(); - private final Map callbacks = new HashMap<>(); + private final Map callbacks = new HashMap<>(); private final ParseCurrentUserController controller; public ParseAuthenticationManager(ParseCurrentUserController controller) { this.controller = controller; } - public void register(final String authType, ParseAuthenticationCallbacks callbacks) { + public void register(final String authType, AuthenticationCallback callback) { if (authType == null) { throw new IllegalArgumentException("Invalid authType: " + null); } synchronized (lock) { if (this.callbacks.containsKey(authType)) { - throw new IllegalStateException("Callbacks already registered for <" + authType + ">: " + throw new IllegalStateException("Callback already registered for <" + authType + ">: " + this.callbacks.get(authType)); } - this.callbacks.put(authType, callbacks); + this.callbacks.put(authType, callback); } if (ParseAnonymousUtils.AUTH_TYPE.equals(authType)) { @@ -43,7 +43,7 @@ public void register(final String authType, ParseAuthenticationCallbacks callbac return; } - // Synchronize the current user with the auth callbacks. + // Synchronize the current user with the auth callback. controller.getAsync(false).onSuccessTask(new Continuation>() { @Override public Task then(Task task) throws Exception { @@ -57,31 +57,31 @@ public Task then(Task task) throws Exception { } public Task restoreAuthenticationAsync(String authType, final Map authData) { - final ParseAuthenticationCallbacks callbacks; + final AuthenticationCallback callback; synchronized (lock) { - callbacks = this.callbacks.get(authType); + callback = this.callbacks.get(authType); } - if (callbacks == null) { + if (callback == null) { return Task.forResult(true); } return Task.call(new Callable() { @Override public Boolean call() throws Exception { - return callbacks.onRestoreAuthentication(authData); + return callback.onRestore(authData); } }, ParseExecutors.io()); } public Task deauthenticateAsync(String authType) { - final ParseAuthenticationCallbacks callbacks; + final AuthenticationCallback callback; synchronized (lock) { - callbacks = this.callbacks.get(authType); + callback = this.callbacks.get(authType); } - if (callbacks != null) { + if (callback != null) { return Task.call(new Callable() { @Override public Void call() throws Exception { - callbacks.onDeauthenticate(); + callback.onRestore(null); return null; } }, ParseExecutors.io()); diff --git a/Parse/src/main/java/com/parse/ParseUser.java b/Parse/src/main/java/com/parse/ParseUser.java index e66e226b6..8315d5985 100644 --- a/Parse/src/main/java/com/parse/ParseUser.java +++ b/Parse/src/main/java/com/parse/ParseUser.java @@ -1079,18 +1079,19 @@ public ParseUser fetchIfNeeded() throws ParseException { //region Third party authentication /** - * Registers third party authentication callbacks. + * Registers a third party authentication callback. *

* Note: This shouldn't be called directly unless developing a third party authentication * library. * - * @param callbacks The third party authentication callbacks to be registered. + * @param authType The name of the third party authentication source. + * @param callback The third party authentication callback to be registered. * - * @see ParseAuthenticationCallbacks + * @see AuthenticationCallback */ - public static void registerAuthenticationCallbacks( - String authType, ParseAuthenticationCallbacks callbacks) { - getAuthenticationManager().register(authType, callbacks); + public static void registerAuthenticationCallback( + String authType, AuthenticationCallback callback) { + getAuthenticationManager().register(authType, callback); } /** @@ -1103,7 +1104,7 @@ public static void registerAuthenticationCallbacks( * @param authData The user credentials of the third party authentication source. * @return A {@code Task} is resolved when logging in completes. * - * @see ParseAuthenticationCallbacks + * @see AuthenticationCallback */ public static Task logInWithInBackground( final String authType, final Map authData) { @@ -1214,7 +1215,7 @@ public Task then(Task task) throws Exception { * @param authType The name of the third party authentication source. * @return {@code true} if linked, otherwise {@code false}. * - * @see ParseAuthenticationCallbacks + * @see AuthenticationCallback */ public boolean isLinked(String authType) { Map> authData = getAuthData(); @@ -1314,7 +1315,7 @@ public Task then(Task task) throws Exception { * @param authData The user credentials of the third party authentication source. * @return A {@code Task} is resolved when linking completes. * - * @see ParseAuthenticationCallbacks + * @see AuthenticationCallback */ public Task linkWithInBackground( String authType, Map authData) { @@ -1333,7 +1334,7 @@ public Task linkWithInBackground( * @param authType The name of the third party authentication source. * @return A {@code Task} is resolved when unlinking completes. * - * @see ParseAuthenticationCallbacks + * @see AuthenticationCallback */ public Task unlinkFromInBackground(final String authType) { if (authType == null) { diff --git a/Parse/src/test/java/com/parse/ParseAuthenticationManagerTest.java b/Parse/src/test/java/com/parse/ParseAuthenticationManagerTest.java index 807207f2d..89769df10 100644 --- a/Parse/src/test/java/com/parse/ParseAuthenticationManagerTest.java +++ b/Parse/src/test/java/com/parse/ParseAuthenticationManagerTest.java @@ -31,13 +31,13 @@ public class ParseAuthenticationManagerTest { private ParseAuthenticationManager manager; private ParseCurrentUserController controller; - private ParseAuthenticationCallbacks provider; + private AuthenticationCallback provider; @Before public void setUp() { controller = mock(ParseCurrentUserController.class); manager = new ParseAuthenticationManager(controller); - provider = mock(ParseAuthenticationCallbacks.class); + provider = mock(AuthenticationCallback.class); } //region testRegister @@ -45,7 +45,7 @@ public void setUp() { @Test public void testRegisterMultipleShouldThrow() { when(controller.getAsync(false)).thenReturn(Task.forResult(null)); - ParseAuthenticationCallbacks provider2 = mock(ParseAuthenticationCallbacks.class); + AuthenticationCallback provider2 = mock(AuthenticationCallback.class); manager.register("test_provider", provider); @@ -55,7 +55,7 @@ public void testRegisterMultipleShouldThrow() { @Test public void testRegisterAnonymous() { - manager.register("anonymous", mock(ParseAuthenticationCallbacks.class)); + manager.register("anonymous", mock(AuthenticationCallback.class)); verifyNoMoreInteractions(controller); } @@ -74,14 +74,14 @@ public void testRegister() { @Test public void testRestoreAuthentication() throws ParseException { when(controller.getAsync(false)).thenReturn(Task.forResult(null)); - when(provider.onRestoreAuthentication(Matchers.>any())) + when(provider.onRestore(Matchers.>any())) .thenReturn(true); manager.register("test_provider", provider); Map authData = new HashMap<>(); ParseTaskUtils.wait(manager.restoreAuthenticationAsync("test_provider", authData)); - verify(provider).onRestoreAuthentication(authData); + verify(provider).onRestore(authData); } @Test @@ -91,6 +91,6 @@ public void testDeauthenticateAsync() throws ParseException { ParseTaskUtils.wait(manager.deauthenticateAsync("test_provider")); - verify(provider).onDeauthenticate(); + verify(provider).onRestore(null); } } diff --git a/Parse/src/test/java/com/parse/ParseUserTest.java b/Parse/src/test/java/com/parse/ParseUserTest.java index ad2a04f76..2af2dab4c 100644 --- a/Parse/src/test/java/com/parse/ParseUserTest.java +++ b/Parse/src/test/java/com/parse/ParseUserTest.java @@ -569,10 +569,10 @@ public void testlinkWithInBackgroundWithSaveAsyncSuccess() throws Exception { when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register mock callbacks - ParseAuthenticationCallbacks callbacks = mock(ParseAuthenticationCallbacks.class); - when(callbacks.onRestoreAuthentication(Matchers.>any())) + AuthenticationCallback callbacks = mock(AuthenticationCallback.class); + when(callbacks.onRestore(Matchers.>any())) .thenReturn(true); - ParseUser.registerAuthenticationCallbacks("facebook", callbacks); + ParseUser.registerAuthenticationCallback("facebook", callbacks); ParseUser user = new ParseUser(); // To make synchronizeAuthData work @@ -600,7 +600,7 @@ public void testlinkWithInBackgroundWithSaveAsyncSuccess() throws Exception { verify(partialMockUser, times(1)) .saveAsync(eq("sessionTokenAgain"), eq(false), Matchers.>any()); // Make sure synchronizeAuthData() is called - verify(callbacks, times(1)).onRestoreAuthentication(authData); + verify(callbacks, times(1)).onRestore(authData); } @Test @@ -1289,10 +1289,10 @@ public void testSynchronizeAuthData() throws Exception { when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(currentUser)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register mock callbacks - ParseAuthenticationCallbacks callbacks = mock(ParseAuthenticationCallbacks.class); - when(callbacks.onRestoreAuthentication(Matchers.>any())) + AuthenticationCallback callbacks = mock(AuthenticationCallback.class); + when(callbacks.onRestore(Matchers.>any())) .thenReturn(true); - ParseUser.registerAuthenticationCallbacks("facebook", callbacks); + ParseUser.registerAuthenticationCallback("facebook", callbacks); // Set user initial state String authType = "facebook"; @@ -1307,7 +1307,7 @@ public void testSynchronizeAuthData() throws Exception { ParseTaskUtils.wait(user.synchronizeAuthDataAsync(authType)); // Make sure we restore authentication - verify(callbacks, times(1)).onRestoreAuthentication(authData); + verify(callbacks, times(1)).onRestore(authData); } @Test @@ -1318,10 +1318,10 @@ public void testSynchronizeAllAuthData() throws Exception { when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(currentUser)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register mock callbacks - ParseAuthenticationCallbacks callbacks = mock(ParseAuthenticationCallbacks.class); - when(callbacks.onRestoreAuthentication(Matchers.>any())) + AuthenticationCallback callbacks = mock(AuthenticationCallback.class); + when(callbacks.onRestore(Matchers.>any())) .thenReturn(true); - ParseUser.registerAuthenticationCallbacks("facebook", callbacks); + ParseUser.registerAuthenticationCallback("facebook", callbacks); // Set user initial state String facebookAuthType = "facebook"; @@ -1336,7 +1336,7 @@ public void testSynchronizeAllAuthData() throws Exception { ParseTaskUtils.wait(user.synchronizeAllAuthDataAsync()); // Make sure we restore authentication - verify(callbacks, times(1)).onRestoreAuthentication(facebookAuthData); + verify(callbacks, times(1)).onRestore(facebookAuthData); } //endregion