Skip to content

Commit 0a09db1

Browse files
authored
Add firebase auth destroy check before tenant operations. (#386)
This addresses some TODOs left as part of the initiative to add multi-tenancy support (see issue #332).
1 parent d4dd47f commit 0a09db1

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,9 +1095,13 @@ private void checkNotDestroyed() {
10951095
}
10961096
}
10971097

1098-
void destroy() {
1098+
final void destroy() {
10991099
synchronized (lock) {
1100+
doDestroy();
11001101
destroyed.set(true);
11011102
}
11021103
}
1104+
1105+
/** Performs any additional required clean up. */
1106+
protected abstract void doDestroy();
11031107
}

src/main/java/com/google/firebase/auth/FirebaseAuth.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.google.firebase.ImplFirebaseTrampolines;
2424
import com.google.firebase.auth.internal.FirebaseTokenFactory;
2525
import com.google.firebase.internal.FirebaseService;
26+
import java.util.concurrent.atomic.AtomicBoolean;
2627

2728
/**
2829
* This class is the entry point for all server-side Firebase Authentication actions.
@@ -37,6 +38,7 @@ public class FirebaseAuth extends AbstractFirebaseAuth {
3738
private static final String SERVICE_ID = FirebaseAuth.class.getName();
3839

3940
private final Supplier<TenantManager> tenantManager;
41+
private final AtomicBoolean tenantManagerCreated = new AtomicBoolean(false);
4042

4143
private FirebaseAuth(final Builder builder) {
4244
super(
@@ -47,6 +49,7 @@ private FirebaseAuth(final Builder builder) {
4749
tenantManager = threadSafeMemoize(new Supplier<TenantManager>() {
4850
@Override
4951
public TenantManager get() {
52+
tenantManagerCreated.set(true);
5053
return new TenantManager(builder.firebaseApp, getUserManager());
5154
}
5255
});
@@ -80,6 +83,14 @@ public static synchronized FirebaseAuth getInstance(FirebaseApp app) {
8083
return service.getInstance();
8184
}
8285

86+
@Override
87+
protected void doDestroy() {
88+
// Only destroy the tenant manager if it has been created.
89+
if (tenantManagerCreated.get()) {
90+
getTenantManager().destroy();
91+
}
92+
}
93+
8394
private static FirebaseAuth fromApp(final FirebaseApp app) {
8495
return FirebaseAuth.builder()
8596
.setFirebaseApp(app)

src/main/java/com/google/firebase/auth/TenantManager.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.google.common.base.Preconditions.checkArgument;
2020
import static com.google.common.base.Preconditions.checkNotNull;
21+
import static com.google.common.base.Preconditions.checkState;
2122

2223
import com.google.api.client.json.JsonFactory;
2324
import com.google.api.core.ApiFuture;
@@ -31,6 +32,7 @@
3132
import com.google.firebase.internal.CallableOperation;
3233
import com.google.firebase.internal.NonNull;
3334
import com.google.firebase.internal.Nullable;
35+
import java.util.concurrent.atomic.AtomicBoolean;
3436

3537
/**
3638
* This class can be used to perform a variety of tenant-related operations, including creating,
@@ -40,6 +42,9 @@
4042
*/
4143
public final class TenantManager {
4244

45+
private final Object lock = new Object();
46+
private final AtomicBoolean destroyed = new AtomicBoolean(false);
47+
4348
private final FirebaseApp firebaseApp;
4449
private final FirebaseUserManager userManager;
4550

@@ -74,7 +79,7 @@ public ApiFuture<Tenant> getTenantAsync(@NonNull String tenantId) {
7479
}
7580

7681
private CallableOperation<Tenant, FirebaseAuthException> getTenantOp(final String tenantId) {
77-
// TODO(micahstairs): Add a check to make sure the app has not been destroyed yet.
82+
checkNotDestroyed();
7883
checkArgument(!Strings.isNullOrEmpty(tenantId), "tenantId must not be null or empty");
7984
return new CallableOperation<Tenant, FirebaseAuthException>() {
8085
@Override
@@ -142,7 +147,7 @@ public ApiFuture<ListTenantsPage> listTenantsAsync(@Nullable String pageToken, i
142147

143148
private CallableOperation<ListTenantsPage, FirebaseAuthException> listTenantsOp(
144149
@Nullable final String pageToken, final int maxResults) {
145-
// TODO(micahstairs): Add a check to make sure the app has not been destroyed yet.
150+
checkNotDestroyed();
146151
final TenantSource tenantSource = new DefaultTenantSource(userManager);
147152
final PageFactory factory = new PageFactory(tenantSource, maxResults, pageToken);
148153
return new CallableOperation<ListTenantsPage, FirebaseAuthException>() {
@@ -180,7 +185,7 @@ public ApiFuture<Tenant> createTenantAsync(@NonNull CreateRequest request) {
180185

181186
private CallableOperation<Tenant, FirebaseAuthException> createTenantOp(
182187
final CreateRequest request) {
183-
// TODO(micahstairs): Add a check to make sure the app has not been destroyed yet.
188+
checkNotDestroyed();
184189
checkNotNull(request, "create request must not be null");
185190
return new CallableOperation<Tenant, FirebaseAuthException>() {
186191
@Override
@@ -218,7 +223,7 @@ public ApiFuture<Tenant> updateTenantAsync(@NonNull UpdateRequest request) {
218223

219224
private CallableOperation<Tenant, FirebaseAuthException> updateTenantOp(
220225
final UpdateRequest request) {
221-
// TODO(micahstairs): Add a check to make sure the app has not been destroyed yet.
226+
checkNotDestroyed();
222227
checkNotNull(request, "update request must not be null");
223228
return new CallableOperation<Tenant, FirebaseAuthException>() {
224229
@Override
@@ -253,7 +258,7 @@ public ApiFuture<Void> deleteTenantAsync(String tenantId) {
253258
}
254259

255260
private CallableOperation<Void, FirebaseAuthException> deleteTenantOp(final String tenantId) {
256-
// TODO(micahstairs): Add a check to make sure the app has not been destroyed yet.
261+
checkNotDestroyed();
257262
checkArgument(!Strings.isNullOrEmpty(tenantId), "tenantId must not be null or empty");
258263
return new CallableOperation<Void, FirebaseAuthException>() {
259264
@Override
@@ -263,4 +268,17 @@ protected Void execute() throws FirebaseAuthException {
263268
}
264269
};
265270
}
271+
272+
void checkNotDestroyed() {
273+
synchronized (lock) {
274+
checkState(
275+
!destroyed.get(),
276+
"TenantManager instance is no longer alive. This happens when "
277+
+ "the parent FirebaseApp instance has been deleted.");
278+
}
279+
}
280+
281+
protected void destroy() {
282+
destroyed.set(true);
283+
}
266284
}

0 commit comments

Comments
 (0)