Skip to content

chore(sdk): Update to Firebase JS SDK 4.0 (breaking changes) #996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions docs/version-4-upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ constructor(db: AngularFireDatabase, afAuth: AngularFireAuth) {

### Simplified Authentication API

In 4.0 we've reduced the complexity of the auth module by providing only a [`firebase.User`](https://firebase.google.com/docs/reference/js/firebase.User) observer (`AngularFireAuth.authState`) and cutting the methods that were wrapping the Firebase SDK.
In 4.0 we've reduced the complexity of the auth module by providing only [`firebase.User`](https://firebase.google.com/docs/reference/js/firebase.User) observers (`AngularFireAuth.authState`, `AngularFireAuth.idToken`) and cutting the methods that were wrapping the Firebase SDK.


```typescript
import { AngularFireAuth } from 'angularfire2/auth';
Expand All @@ -40,7 +41,7 @@ import * as firebase from 'firebase/app';

user: Observable<firebase.User>;
constructor(afAuth: AngularFireAuth) {
this.user = afAuth.authState;
this.user = afAuth.authState; // only triggered on sign-in/out (for old behavior use .idToken)
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need more here to explain how to use both? It seems like most users will just go with .idToken since it behaves like authState did. We should also update the main Authentication doc, but I guess we could do that after this PR is merged.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes we'll definitely address this in the auth section of the docs.

}
```

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@angular/core": "^4.0.0",
"@angular/platform-browser": "^4.0.0",
"@angular/platform-browser-dynamic": "^4.0.0",
"firebase": "^3.6.6",
"firebase": "^4.0.0",
"rxjs": "^5.0.1"
},
"devDependencies": {
Expand Down
45 changes: 34 additions & 11 deletions src/auth/auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,9 @@ const firebaseUser = <firebase.User> {

describe('AngularFireAuth', () => {
let app: firebase.app.App;
let authData: any;
let authCb: any;
let afAuth: AngularFireAuth;
let authSpy: jasmine.Spy;
let mockAuthState: Subject<firebase.User>;
let fbAuthObserver: Observer<firebase.User>;
let windowLocation: any;

beforeEach(() => {
TestBed.configureTestingModule({
Expand All @@ -45,13 +41,13 @@ describe('AngularFireAuth', () => {
inject([FirebaseApp, AngularFireAuth], (app_: FirebaseApp, _auth: AngularFireAuth) => {
app = app_;
afAuth = _auth;
authData = null;
authCb = null;
})();

mockAuthState = new Subject<firebase.User>();
spyOn(afAuth, 'authState').and.returnValue(mockAuthState);
spyOn(afAuth, 'idToken').and.returnValue(mockAuthState);
afAuth.authState = mockAuthState;
afAuth.idToken = mockAuthState;
});

afterEach(done => {
Expand All @@ -65,12 +61,18 @@ describe('AngularFireAuth', () => {
name: 'ngZone'
});
ngZone.run(() => {
const subs = afAuth.authState.subscribe(user => {
expect(Zone.current.name).toBe('ngZone');
done();
}, done.fail);
const subs = [
afAuth.authState.subscribe(user => {
expect(Zone.current.name).toBe('ngZone');
done();
}, done.fail),
afAuth.authState.subscribe(user => {
expect(Zone.current.name).toBe('ngZone');
done();
}, done.fail)
];
mockAuthState.next(firebaseUser);
subs.unsubscribe();
subs.forEach(s => s.unsubscribe());
});
});
});
Expand All @@ -88,6 +90,27 @@ describe('AngularFireAuth', () => {

// Check that the first value is null and second is the auth user
const subs = afAuth.authState.subscribe(user => {
console.log('What...', count, user);
if (count === 0) {
expect(user).toBe(null);
count = count + 1;
mockAuthState.next(firebaseUser);
} else {
expect(user).toEqual(firebaseUser);
subs.unsubscribe();
done();
}
}, done, done.fail);
console.log('....!?');
mockAuthState.next(null);
});

it('should emit auth updates through idToken', (done: any) => {
let count = 0;

// Check that the first value is null and second is the auth user
const subs = afAuth.idToken.subscribe(user => {
console.log("HI!....", count, user);
if (count === 0) {
expect(user).toBe(null);
count = count + 1;
Expand Down
24 changes: 23 additions & 1 deletion src/auth/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ export class AngularFireAuth {
auth: firebase.auth.Auth;

/**
* Observable of authentication state
* Observable of authentication state; as of 4.0 this is only triggered via sign-in/out
*/
authState: Observable<firebase.User>;

/**
* Observable of the signed-in user's ID token; which includes sign-in, sign-out, and token refresh events
*/
idToken: Observable<firebase.User>;

constructor(public app: FirebaseApp) {
this.authState = FirebaseAuthStateObservable(app);
this.idToken = FirebaseIdTokenObservable(app);
this.auth = app.auth();
}

Expand All @@ -43,3 +49,19 @@ export function FirebaseAuthStateObservable(app: FirebaseApp): Observable<fireba
});
return observeOn.call(authState, new utils.ZoneScheduler(Zone.current));
}

/**
* Create an Observable of Firebase ID token. Each event is called
* within the current zone.
* @param app - Firebase App instance
*/
export function FirebaseIdTokenObservable(app: FirebaseApp): Observable<firebase.User> {
const idToken = Observable.create((observer: Observer<firebase.User>) => {
app.auth().onIdTokenChanged(
(user?: firebase.User) => observer.next(user),
(error: firebase.auth.Error) => observer.error(error),
() => observer.complete()
)
});
return observeOn.call(idToken, new utils.ZoneScheduler(Zone.current));
}
Loading