Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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 @@ -16,6 +16,8 @@

package com.mongodb.stitch.android.core.auth;

import javax.annotation.Nullable;

/**
* StitchAuthListener allows one to hook into authentication events as they happen in a Stitch app
* client.
Expand All @@ -29,10 +31,113 @@ public interface StitchAuthListener {
* - When a user logs out.
* - When a user is linked to another identity.
* - When a listener is registered. This is to handle the case where during registration
* an event happens that the registerer would otherwise miss out on.
* an event happens that the registerer would otherwise miss out on.
* - When switching users.
*
* @param auth the instance of {@link StitchAuth} where the event happened. It should be used to
* infer the current state of authentication.
* infer the current state of authentication.
*/
@Deprecated
default void onAuthEvent(final StitchAuth auth) {

}

/**
* Called whenever a user is added to the device for the first time. If this
* is as part of a login, this method will be called before
* {@link #onUserLoggedIn}, and {@link #onActiveUserChanged}
* are called.
*
* @param auth The instance of {@link StitchAuth} where the user was added.
* It can be used to infer the current state of authentication.
* @param addedUser The user that was added to the device.
*/
default void onUserAdded(final StitchAuth auth, final StitchUser addedUser) {
}

/**
* Called whenever a user is logged in. This will be called before
* {@link #onActiveUserChanged} is called.
* Note: if an anonymous user was already logged in on the device, and you
* log in with an {@link com.mongodb.stitch.core.auth.providers.anonymous.AnonymousCredential},
* this method will not be called,
* as the underlying {@link StitchAuth} will reuse the anonymous user's existing
* session, and will thus only trigger {@link #onActiveUserChanged}.
*
* @param auth The instance of {@link StitchAuth} where the user was logged in.
* It can be used to infer the current state of authentication.
* @param loggedInUser The user that was logged in.
*/
default void onUserLoggedIn(final StitchAuth auth,
final StitchUser loggedInUser) {
}

/**
* Called whenever a user is linked to a new identity.
*
* @param auth The instance of {@link StitchAuth} where the user was linked.
* It can be used to infer the current state of authentication.
* @param linkedUser The user that was linked to a new identity.
*/
default void onUserLinked(final StitchAuth auth, final StitchUser linkedUser) {

}

/**
* Called whenever a user is logged out. The user logged out is not
* necessarily the active user. If the user logged out was the active user,
* then {@link #onActiveUserChanged} will be called after this method. If the user
* was an anonymous user, that user will also be removed and
* {@link #onUserRemoved} will also be called.
*
* @param auth The instance of {@link StitchAuth} where the user was logged out.
* It can be used to infer the current state of authentication.
* @param loggedOutUser The user that was logged out.
*/
default void onUserLoggedOut(final StitchAuth auth, final StitchUser loggedOutUser) {

}

/**
* Called whenever the active user changes. This may be due to a call to
* {@link StitchAuth#loginWithCredential}, {@link StitchAuth#switchToUserWithId},
* {@link StitchAuth#logout}, {@link StitchAuth#logoutUserWithId},
* {@link StitchAuth#removeUser}, or {@link StitchAuth#removeUserWithId}.
* This may also occur on a normal request if a user's session is invalidated
* and they are forced to log out.
*
* @param auth The instance of {@link StitchAuth} where the active user changed.
* It can be used to infer the current state of authentication.
* @param currentActiveUser The active user after the change.
* @param previousActiveUser The active user before the change.
*/
default void onActiveUserChanged(final StitchAuth auth,
@Nullable final StitchUser currentActiveUser,
@Nullable final StitchUser previousActiveUser) {

}

/**
* Called whenever a user is removed from the list of users on the device.
*
* @param auth The instance of {@link StitchAuth} where the user was removed.
* It can be used to infer the current state of authentication.
* @param removedUser The user that was removed.
*/
void onAuthEvent(final StitchAuth auth);
default void onUserRemoved(final StitchAuth auth, final StitchUser removedUser) {

}

/**
* Called whenever this listener is registered for the first time. This can
* be useful to infer the state of authentication, because any events that
* occurred before the listener was registered will not be seen by the
* listener.
*
* @param auth The instance of {@link StitchAuth} where the listener was registered.
* It can be used to infer the current state of authentication.
*/
default void onListenerRegistered(final StitchAuth auth) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.annotation.Nullable;
import org.bson.Document;

/**
Expand Down Expand Up @@ -195,6 +196,14 @@ public void addAuthListener(final StitchAuthListener listener) {
// Trigger the onUserLoggedIn event in case some event happens and
// this caller would miss out on this event other wise.
onAuthEvent(listener);
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onListenerRegistered(StitchAuthImpl.this);
return null;
}
});
}

public void addSynchronousAuthListener(final StitchAuthListener listener) {
Expand All @@ -205,6 +214,7 @@ public void addSynchronousAuthListener(final StitchAuthListener listener) {
// Trigger the onUserLoggedIn event in case some event happens and
// this caller would miss out on this event other wise.
onAuthEvent(listener);
listener.onListenerRegistered(this);
}

/**
Expand All @@ -231,10 +241,141 @@ public Void call() {
@Override
protected void onAuthEvent() {
for (final StitchAuthListener listener : listeners) {
onAuthEvent(listener);
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onAuthEvent(StitchAuthImpl.this);
return null;
}
});
}
for (final StitchAuthListener listener : synchronousListeners) {
listener.onAuthEvent(this);
}
}

@Override
protected void onListenerInitialized() {
for (final StitchAuthListener listener : listeners) {
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onListenerRegistered(StitchAuthImpl.this);
return null;
}
});
}
for (final StitchAuthListener listener : synchronousListeners) {
listener.onListenerRegistered(this);
}
}

@Override
protected void onActiveUserChanged(@Nullable final StitchUser currentActiveUser,
@Nullable final StitchUser previousActiveUser) {
for (final StitchAuthListener listener : listeners) {
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onActiveUserChanged(
StitchAuthImpl.this, currentActiveUser, previousActiveUser);
return null;
}
});
}
for (final StitchAuthListener listener : synchronousListeners) {
listener.onActiveUserChanged(
this, currentActiveUser, previousActiveUser);
}
}

@Override
protected void onUserAdded(final StitchUser createdUser) {
for (final StitchAuthListener listener : listeners) {
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onUserAdded(
StitchAuthImpl.this, createdUser);
return null;
}
});
}
for (final StitchAuthListener listener : synchronousListeners) {
listener.onUserAdded(this, createdUser);
}
}

@Override
protected void onUserLoggedIn(final StitchUser loggedInUser) {
for (final StitchAuthListener listener : listeners) {
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onUserLoggedIn(
StitchAuthImpl.this, loggedInUser);
return null;
}
});
}
for (final StitchAuthListener listener : synchronousListeners) {
listener.onUserLoggedIn(this, loggedInUser);
}
}

@Override
protected void onUserRemoved(final StitchUser removedUser) {
for (final StitchAuthListener listener : listeners) {
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onUserRemoved(StitchAuthImpl.this, removedUser);
return null;
}
});
}
for (final StitchAuthListener listener : synchronousListeners) {
listener.onUserRemoved(this, removedUser);
}
}

@Override
protected void onUserLoggedOut(final StitchUser loggedOutUser) {
for (final StitchAuthListener listener : listeners) {
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onUserLoggedOut(StitchAuthImpl.this, loggedOutUser);
return null;
}
});
}
for (final StitchAuthListener listener : synchronousListeners) {
listener.onUserLoggedOut(this, loggedOutUser);
}
}

@Override
protected void onUserLinked(final StitchUser linkedUser) {
for (final StitchAuthListener listener : listeners) {
dispatcher.dispatchTask(
new Callable<Void>() {
@Override
public Void call() {
listener.onUserLinked(StitchAuthImpl.this, linkedUser);
return null;
}
});
}
for (final StitchAuthListener listener : synchronousListeners) {
listener.onUserLinked(this, linkedUser);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.mongodb.stitch.android.core.StitchAppClient;
import com.mongodb.stitch.android.core.auth.StitchAuth;
import com.mongodb.stitch.android.core.auth.StitchAuthListener;
import com.mongodb.stitch.android.core.auth.StitchUser;
import com.mongodb.stitch.android.core.auth.internal.StitchAuthImpl;
import com.mongodb.stitch.android.core.internal.common.MainLooperDispatcher;
import com.mongodb.stitch.android.core.internal.common.TaskDispatcher;
Expand All @@ -31,12 +32,15 @@
import com.mongodb.stitch.android.core.services.internal.StitchServiceClientImpl;
import com.mongodb.stitch.core.StitchAppClientConfiguration;
import com.mongodb.stitch.core.StitchAppClientInfo;
import com.mongodb.stitch.core.auth.internal.CoreStitchAuth;
import com.mongodb.stitch.core.internal.CoreStitchAppClient;
import com.mongodb.stitch.core.internal.common.AuthMonitor;
import com.mongodb.stitch.core.internal.net.StitchAppRequestClientImpl;
import com.mongodb.stitch.core.internal.net.StitchAppRoutes;
import com.mongodb.stitch.core.services.internal.AuthEvent;
import com.mongodb.stitch.core.services.internal.CoreStitchServiceClient;
import com.mongodb.stitch.core.services.internal.CoreStitchServiceClientImpl;
import com.mongodb.stitch.core.services.internal.RebindEvent;

import java.io.IOException;
import java.lang.ref.WeakReference;
Expand Down Expand Up @@ -271,8 +275,17 @@ public ResultT call() {
}

@Override
public boolean isLoggedIn() {
return getAuth().isLoggedIn();
public boolean isLoggedIn() throws InterruptedException {
return ((CoreStitchAuth)getAuth()).isLoggedInInterruptibly();
}

@Override
public boolean tryIsLoggedIn() {
try {
return ((CoreStitchAuth)getAuth()).isLoggedInInterruptibly();
} catch (InterruptedException e) {
return false;
}
}

@Nullable
Expand All @@ -293,8 +306,7 @@ private void bindServiceClient(final CoreStitchServiceClient coreStitchServiceCl
this.serviceClients.add(new WeakReference<>(coreStitchServiceClient));
}

@Override
public void onAuthEvent(final StitchAuth auth) {
private void onRebindEvent(final RebindEvent rebindEvent) {
final Iterator<WeakReference<CoreStitchServiceClient>> iterator =
this.serviceClients.iterator();
while (iterator.hasNext()) {
Expand All @@ -305,11 +317,39 @@ public void onAuthEvent(final StitchAuth auth) {
if (binder == null) {
this.serviceClients.remove(weakReference);
} else {
binder.onRebindEvent();
binder.onRebindEvent(rebindEvent);
}
}
}

@Override
public void onAuthEvent(final StitchAuth auth) {
}

@Override
public void onUserLoggedIn(final StitchAuth auth,
final StitchUser loggedInUser) {
onRebindEvent(new AuthEvent.UserLoggedIn<>(loggedInUser));
Copy link
Contributor

Choose a reason for hiding this comment

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

Should you be rebinding on all of these?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it is up to the service to determine what to do with the information given.

}

@Override
public void onUserLoggedOut(final StitchAuth auth,
final StitchUser loggedOutUser) {
onRebindEvent(new AuthEvent.UserLoggedOut<>(loggedOutUser));
}

@Override
public void onActiveUserChanged(final StitchAuth auth,
final StitchUser currentActiveUser,
final @Nullable StitchUser previousActiveUser) {
onRebindEvent(new AuthEvent.ActiveUserChanged<>(currentActiveUser, previousActiveUser));
}

@Override
public void onUserRemoved(final StitchAuth auth, final StitchUser removedUser) {
onRebindEvent(new AuthEvent.UserRemoved<>(removedUser));
}

/**
* Closes the client and shuts down all background operations.
*/
Expand Down
Loading