@Override public Task<Void> setIfNeededAsync(ParseUser user) { synchronized (mutex) { if (!user.isCurrentUser() || currentUserMatchesDisk) { return Task.forResult(null); } } return setAsync(user); }
/** * Ensures that all auth sources 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); }
@Override /* package */ void validateSave() { synchronized (mutex) { if (getObjectId() == null) { throw new IllegalArgumentException( "Cannot save a ParseUser until it has been signed up. Call signUp first."); } if (isAuthenticated() || !isDirty() || isCurrentUser()) { return; } } if (!Parse.isLocalDatastoreEnabled()) { // This might be a different of instance of the currentUser, so we need to check objectIds ParseUser current = ParseUser.getCurrentUser(); //TODO (grantland): possible blocking disk i/o if (current != null && getObjectId().equals(current.getObjectId())) { return; } } throw new IllegalArgumentException("Cannot save a ParseUser that is not authenticated."); }
ParseACL acl = (ParseACL) root; ParseUser user = acl.getUnresolvedUser(); if (user != null && user.isCurrentUser()) { traverseInternal(user, true, seen);
/* package for tests */ Task<Void> saveAsync(String sessionToken, boolean isLazy, Task<Void> toAwait) { Task<Void> task; if (isLazy) { task = resolveLazinessAsync(toAwait); } else { task = super.saveAsync(sessionToken, toAwait); } if (isCurrentUser()) { // If the user is the currently logged in user, we persist all data to disk return task.onSuccessTask(new Continuation<Void, Task<Void>>() { @Override public Task<Void> then(Task<Void> task) { return cleanUpAuthDataAsync(); } }).onSuccessTask(new Continuation<Void, Task<Void>>() { @Override public Task<Void> then(Task<Void> task) { return saveCurrentUserAsync(ParseUser.this); } }); } return task; }
@Override public Task<Void> then(Task<Void> task) { if (!object.isDataAvailable(KEY_ACL)) { return Task.forResult(null); } final ParseACL acl = object.getACL(false); if (acl == null) { return Task.forResult(null); } ParseUser user = acl.getUnresolvedUser(); if (user == null || !user.isCurrentUser()) { return Task.forResult(null); } return ParseUser.pinCurrentUserIfNeededAsync(user); } });
@SuppressWarnings("unchecked") @Override /* package */ <T extends ParseObject> Task<T> fetchAsync( String sessionToken, Task<Void> toAwait) { //TODO (grantland): It doesn't seem like we should do this.. Why don't we error like we do // when fetching an unsaved ParseObject? if (isLazy()) { return Task.forResult((T) this); } Task<T> task = super.fetchAsync(sessionToken, toAwait); if (isCurrentUser()) { return task.onSuccessTask(new Continuation<T, Task<Void>>() { @Override public Task<Void> then(final Task<T> fetchAsyncTask) { return cleanUpAuthDataAsync(); } }).onSuccessTask(new Continuation<Void, Task<Void>>() { @Override public Task<Void> then(Task<Void> task) { return saveCurrentUserAsync(ParseUser.this); } }).onSuccess(new Continuation<Void, T>() { @Override public T then(Task<Void> task) { return (T) ParseUser.this; } }); } return task; }
@Override /* package */ void setState(ParseObject.State newState) { if (isCurrentUser()) { State.Builder newStateBuilder = newState.newBuilder(); // Avoid clearing sessionToken when updating the current user's State via ParseQuery result if (getSessionToken() != null && newState.get(KEY_SESSION_TOKEN) == null) { newStateBuilder.put(KEY_SESSION_TOKEN, getSessionToken()); } // Avoid clearing authData when updating the current user's State via ParseQuery result if (getAuthData().size() > 0 && newState.get(KEY_AUTH_DATA) == null) { newStateBuilder.put(KEY_AUTH_DATA, getAuthData()); } newState = newStateBuilder.build(); } super.setState(newState); }
@Test public void testGetAsyncWithCurrentUserReadFromDiskFailureAndLazyLogin() throws Exception { ParseObjectStore<ParseUser> store = (ParseObjectStore<ParseUser>) mock(ParseObjectStore.class); when(store.getAsync()).thenReturn(Task.<ParseUser>forError(new RuntimeException("failure"))); CachedCurrentUserController controller = new CachedCurrentUserController(store); ParseUser currentUser = ParseTaskUtils.wait(controller.getAsync(true)); // We need to make sure the user is created by lazy login assertTrue(currentUser.isLazy()); assertTrue(currentUser.isCurrentUser()); assertSame(controller.currentUser, currentUser); assertFalse(controller.currentUserMatchesDisk); // We do not test the lazy login auth data here, it is covered in lazyLogin() unit test }
@Test public void testSetAsyncWithPersistFailure() throws Exception { // Mock currentUser in memory ParseUser oldCurrentUser = mock(ParseUser.class); when(oldCurrentUser.logOutAsync(anyBoolean())).thenReturn(Task.<Void>forResult(null)); ParseUser currentUser = new ParseUser(); ParseObjectStore<ParseUser> store = (ParseObjectStore<ParseUser>) mock(ParseObjectStore.class); when(store.setAsync(currentUser)) .thenReturn(Task.<Void>forError(new RuntimeException("failure"))); CachedCurrentUserController controller = new CachedCurrentUserController(store); controller.currentUser = oldCurrentUser; ParseTaskUtils.wait(controller.setAsync(currentUser)); // Make sure oldCurrentUser logout verify(oldCurrentUser, times(1)).logOutAsync(false); // Verify we tried to persist verify(store, times(1)).setAsync(currentUser); // TODO(mengyan): Find a way to verify user.synchronizeAllAuthData() is called // Verify newUser is currentUser assertTrue(currentUser.isCurrentUser()); // Make sure in memory currentUser is up to date assertSame(currentUser, controller.currentUser); // Make sure in currentUserMatchesDisk since we can not write to disk assertFalse(controller.currentUserMatchesDisk); }
@Test public void testLazyLogin() { CachedCurrentUserController controller = new CachedCurrentUserController(null); String authType = ParseAnonymousUtils.AUTH_TYPE; Map<String, String> authData = new HashMap<>(); authData.put("sessionToken", "testSessionToken"); ParseUser user = controller.lazyLogIn(authType, authData); // Make sure use is generated through lazyLogin assertTrue(user.isLazy()); assertTrue(user.isCurrentUser()); Map<String, Map<String, String>> authPair = user.getMap(KEY_AUTH_DATA); assertEquals(1, authPair.size()); Map<String, String> authDataAgain = authPair.get(authType); assertEquals(1, authDataAgain.size()); assertEquals("testSessionToken", authDataAgain.get("sessionToken")); // Make sure controller state is correct assertSame(user, controller.currentUser); assertFalse(controller.currentUserMatchesDisk); }
@Test public void testSetAsyncWithOldInMemoryCurrentUser() throws Exception { // Mock currentUser in memory ParseUser oldCurrentUser = mock(ParseUser.class); when(oldCurrentUser.logOutAsync(anyBoolean())).thenReturn(Task.<Void>forResult(null)); ParseUser.State state = new ParseUser.State.Builder() .put("key", "value") .build(); ParseUser currentUser = ParseObject.from(state); ParseObjectStore<ParseUser> store = (ParseObjectStore<ParseUser>) mock(ParseObjectStore.class); when(store.setAsync(currentUser)).thenReturn(Task.<Void>forResult(null)); CachedCurrentUserController controller = new CachedCurrentUserController(store); controller.currentUser = oldCurrentUser; ParseTaskUtils.wait(controller.setAsync(currentUser)); // Make sure oldCurrentUser logout verify(oldCurrentUser, times(1)).logOutAsync(false); // Verify it was persisted verify(store, times(1)).setAsync(currentUser); // TODO(mengyan): Find a way to verify user.synchronizeAllAuthData() is called // Verify newUser is currentUser assertTrue(currentUser.isCurrentUser()); // Make sure in memory currentUser is up to date assertSame(currentUser, controller.currentUser); assertTrue(controller.currentUserMatchesDisk); }
@Test public void testSetAsyncWithNoInMemoryCurrentUser() throws Exception { ParseUser.State state = new ParseUser.State.Builder() .put("key", "value") .build(); ParseUser currentUser = ParseObject.from(state); ParseObjectStore<ParseUser> store = (ParseObjectStore<ParseUser>) mock(ParseObjectStore.class); when(store.setAsync(currentUser)).thenReturn(Task.<Void>forResult(null)); CachedCurrentUserController controller = new CachedCurrentUserController(store); ParseTaskUtils.wait(controller.setAsync(currentUser)); // Verify it was persisted verify(store, times(1)).setAsync(currentUser); // TODO(mengyan): Find a way to verify user.synchronizeAllAuthData() is called // Verify newUser is currentUser assertTrue(currentUser.isCurrentUser()); // Make sure in memory currentUser is up to date assertSame(currentUser, controller.currentUser); assertTrue(controller.currentUserMatchesDisk); }
@Test public void testGetAsyncWithNoInMemoryCurrentUserAndLazyLogin() throws Exception { ParseObjectStore<ParseUser> store = (ParseObjectStore<ParseUser>) mock(ParseObjectStore.class); when(store.getAsync()).thenReturn(Task.<ParseUser>forResult(null)); CachedCurrentUserController controller = new CachedCurrentUserController(store); ParseCorePlugins.getInstance().registerCurrentUserController(controller); // CurrentUser is null but currentUserMatchesDisk is true happens when a user logout controller.currentUserMatchesDisk = true; ParseUser currentUser = ParseTaskUtils.wait(controller.getAsync(true)); // We need to make sure the user is created by lazy login assertTrue(currentUser.isLazy()); assertTrue(currentUser.isCurrentUser()); assertSame(controller.currentUser, currentUser); assertFalse(controller.currentUserMatchesDisk); // We do not test the lazy login auth data here, it is covered in lazyLogin() unit test }
@Test public void testGetAsyncWithCurrentUserReadFromDiskSuccess() throws Exception { ParseUser.State state = new ParseUser.State.Builder() .put("key", "value") .build(); ParseUser currentUserInDisk = ParseObject.from(state); ParseObjectStore<ParseUser> store = (ParseObjectStore<ParseUser>) mock(ParseObjectStore.class); when(store.getAsync()).thenReturn(Task.forResult(currentUserInDisk)); CachedCurrentUserController controller = new CachedCurrentUserController(store); ParseUser currentUser = ParseTaskUtils.wait(controller.getAsync(false)); assertSame(currentUser, currentUserInDisk); assertSame(currentUser, controller.currentUser); assertTrue(controller.currentUserMatchesDisk); assertTrue(currentUser.isCurrentUser()); assertEquals("value", currentUser.get("key")); }
@Test public void testOnSaveRestoreState() { ParseUser user = new ParseUser(); user.setObjectId("objId"); user.setIsCurrentUser(true); Parcel parcel = Parcel.obtain(); user.writeToParcel(parcel, 0); parcel.setDataPosition(0); user = (ParseUser) ParseObject.CREATOR.createFromParcel(parcel); assertTrue(user.isCurrentUser()); }