/* * Copyright 2016 Jacek Marchwicki <jacek.marchwicki@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.appunite.rx.example.dao.auth; import android.support.annotation.NonNull; import com.appunite.rx.ResponseOrError; import com.appunite.rx.example.internal.Objects; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.auth.GetTokenResult; import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nonnull; import rx.Observable; import rx.Subscriber; import rx.functions.Action0; import rx.subscriptions.Subscriptions; public class FirebaseCurrentLoggedInUserDao implements MyCurrentLoggedInUserDao { private final Observable<ResponseOrError<LoggedInUserDao>> currentLoggedInUserObservable; private static class FirebaseLoggedInUserDao implements LoggedInUserDao { @Nonnull private final FirebaseUser firebaseUser; FirebaseLoggedInUserDao(@Nonnull FirebaseUser firebaseUser) { this.firebaseUser = firebaseUser; } @Nonnull @Override public String userId() { return firebaseUser.getUid(); } @Nonnull @Override public Observable<String> authTokenObservable(final boolean forceRefresh) { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(final Subscriber<? super String> subscriber) { final Task<GetTokenResult> token = firebaseUser.getToken(forceRefresh); final OnCompleteListener<GetTokenResult> listener = new OnCompleteListener<GetTokenResult>() { @Override public void onComplete(@NonNull Task<GetTokenResult> task) { if (subscriber.isUnsubscribed()) { return; } final Exception exception = task.getException(); if (exception != null) { subscriber.onError(exception); } else { subscriber.onNext(task.getResult().getToken()); subscriber.onCompleted(); } } }; token.addOnCompleteListener(listener); } }); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof FirebaseLoggedInUserDao)) return false; final FirebaseLoggedInUserDao that = (FirebaseLoggedInUserDao) o; return Objects.equal(firebaseUser.getUid(), that.firebaseUser.getUid()); } @Override public int hashCode() { return Objects.hashCode(firebaseUser.getUid()); } } public FirebaseCurrentLoggedInUserDao() { currentLoggedInUserObservable = Observable .create(new Observable.OnSubscribe<ResponseOrError<LoggedInUserDao>>() { @Override public void call(final Subscriber<? super ResponseOrError<LoggedInUserDao>> subscriber) { final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(); final AtomicReference<Object> previous = new AtomicReference<Object>("Wrong"); final FirebaseAuth.AuthStateListener listener = new FirebaseAuth.AuthStateListener() { @Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { final FirebaseUser currentUser = firebaseAuth.getCurrentUser(); final Object old = previous.get(); if (old == currentUser) { return; } previous.set(currentUser); if (currentUser == null) { subscriber.onNext(ResponseOrError.<LoggedInUserDao>fromError(new NotAuthorizedException("Not yet authorized"))); } else { subscriber.onNext(ResponseOrError.<LoggedInUserDao>fromData(new FirebaseLoggedInUserDao(currentUser))); } } }; firebaseAuth.addAuthStateListener(listener); subscriber.add(Subscriptions.create(new Action0() { @Override public void call() { firebaseAuth.removeAuthStateListener(listener); } })); } }) .onBackpressureLatest() .replay(1) .refCount(); } @Nonnull @Override public Observable<ResponseOrError<LoggedInUserDao>> currentLoggedInUserObservable() { return currentLoggedInUserObservable; } }