Skip to content

Commit 12aa422

Browse files
committed
feat(auth): New Auth API
1 parent b388627 commit 12aa422

5 files changed

Lines changed: 34 additions & 255 deletions

File tree

‎src/angularfire2.ts‎

Lines changed: 6 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,100 +2,29 @@ import * as firebase from 'firebase/app';
22
import * as utils from './utils';
33
import { FirebaseAppConfigToken, FirebaseApp, _firebaseAppFactory } from './app/index';
44
import { FirebaseListFactoryOpts, FirebaseObjectFactoryOpts, FirebaseAppConfig } from './interfaces';
5-
import { FirebaseAppName, WindowLocation, FirebaseAuthConfig } from './tokens';
5+
import { FirebaseAppName } from './tokens';
66
import { Injectable, OpaqueToken, NgModule } from '@angular/core';
77
import { FirebaseSdkAuthBackend, AuthBackend, AngularFireAuth, AuthConfiguration } from './auth/index';
88

9-
@Injectable()
10-
export class AngularFire {
11-
constructor(
12-
public auth: AngularFireAuth) {}
13-
}
14-
15-
export function _getAngularFire(auth: AngularFireAuth) {
16-
return new AngularFire(auth);
17-
}
18-
19-
export function _getAngularFireAuth(backend: AuthBackend, location: any, config: any) {
20-
return new AngularFireAuth(backend, location, config);
21-
}
22-
23-
export function _getWindowLocation(){
24-
return window.location;
25-
}
26-
27-
export function _getFirebaseAuthBackend(app: FirebaseApp) {
28-
return new FirebaseSdkAuthBackend(app);
29-
}
30-
31-
export const AuthBackendProvder = {
32-
provide: AuthBackend,
33-
useFactory: _getFirebaseAuthBackend,
34-
deps: [ FirebaseApp ]
35-
};
36-
37-
export const WindowLocationProvider = {
38-
provide: WindowLocation,
39-
useFactory: _getWindowLocation
40-
};
41-
429
export const FirebaseAppProvider = {
4310
provide: FirebaseApp,
4411
useFactory: _firebaseAppFactory,
4512
deps: [ FirebaseAppConfigToken, FirebaseAppName ]
4613
};
4714

48-
export const FirebaseAuthBackendProvider = {
49-
provide: FirebaseSdkAuthBackend,
50-
useFactory: _getFirebaseAuthBackend,
51-
deps: [ FirebaseApp ]
52-
};
53-
54-
export const AngularFireAuthProvider = {
55-
provide: AngularFireAuth,
56-
useFactory: _getAngularFireAuth,
57-
deps: [ AuthBackend, WindowLocation, FirebaseAuthConfig ]
58-
};
59-
60-
export const AngularFireProvider = {
61-
provide: AngularFire,
62-
useFactory: _getAngularFire,
63-
deps: [ AngularFireAuth ]
64-
};
65-
66-
export const FIREBASE_PROVIDERS:any[] = [
67-
FirebaseAppProvider,
68-
FirebaseAuthBackendProvider,
69-
AuthBackendProvder,
70-
WindowLocationProvider,
71-
AngularFireAuthProvider,
72-
AngularFireProvider
73-
];
74-
75-
export {
76-
FirebaseApp,
77-
FirebaseAppConfigToken,
78-
AngularFireAuth,
79-
WindowLocation
80-
}
81-
82-
export { AuthMethods, firebaseAuthConfig, AuthProviders, FirebaseAuthState } from './auth/index';
83-
84-
export { FirebaseConfig, FirebaseAuthConfig, FirebaseRef, FirebaseUrl, FirebaseUserConfig } from './tokens';
85-
export { FirebaseAppConfig } from './interfaces';
86-
8715
@NgModule({
88-
providers: [FIREBASE_PROVIDERS],
16+
providers: [ FirebaseAppProvider ],
8917
})
9018
export class AngularFireModule {
91-
static initializeApp(config: FirebaseAppConfig, authConfig?: AuthConfiguration, appName?: string) {
19+
static initializeApp(config: FirebaseAppConfig, appName?: string) {
9220
return {
9321
ngModule: AngularFireModule,
9422
providers: [
9523
{ provide: FirebaseAppConfigToken, useValue: config },
96-
{ provide: FirebaseAppName, useValue: appName },
97-
{ provide: FirebaseAuthConfig, useValue: authConfig }
24+
{ provide: FirebaseAppName, useValue: appName }
9825
]
9926
}
10027
}
10128
}
29+
30+
export { FirebaseApp, FirebaseAppConfigToken, FirebaseAppConfig }

‎src/auth/auth.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { TestBed, inject } from '@angular/core/testing';
77
import { _do } from 'rxjs/operator/do';
88
import { take } from 'rxjs/operator/take';
99
import { skip } from 'rxjs/operator/skip';
10-
import { FIREBASE_PROVIDERS, FirebaseApp, FirebaseAppConfig, FirebaseAuthState, FirebaseAppConfigToken, AngularFireAuth, AuthMethods, firebaseAuthConfig, AuthProviders, WindowLocation, AngularFireModule } from '../angularfire2';
11-
import { COMMON_CONFIG, ANON_AUTH_CONFIG } from '../test-config';
10+
import { FirebaseApp, FirebaseAppConfig, AngularFireModule } from '../angularfire2';
11+
import { COMMON_CONFIG } from '../test-config';
1212
import { AuthBackend } from './auth_backend';
1313
import { FirebaseSdkAuthBackend } from './firebase_sdk_auth_backend';
1414

‎src/auth/auth.ts‎

Lines changed: 23 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -1,188 +1,37 @@
11
import * as firebase from 'firebase/app';
2+
import * as utils from '../utils';
23
import 'firebase/auth';
3-
import { Provider, Inject, Injectable, Optional } from '@angular/core';
4+
import { Injectable, NgZone } from '@angular/core';
5+
import { Auth } from '../interfaces';
46
import { Observable } from 'rxjs/Observable';
5-
import { Observer } from 'rxjs/Observer';
6-
import { ReplaySubject } from 'rxjs/ReplaySubject';
7-
import { FirebaseApp, FirebaseAuthConfig, WindowLocation } from '../tokens';
8-
import * as utils from '../utils';
9-
import {
10-
authDataToAuthState,
11-
AuthBackend,
12-
AuthProviders,
13-
AuthMethods,
14-
EmailPasswordCredentials,
15-
AuthConfiguration,
16-
FirebaseAuthState,
17-
stripProviderId
18-
} from './auth_backend';
19-
import { mergeMap } from 'rxjs/operator/mergeMap';
20-
import { of as observableOf } from 'rxjs/observable/of';
21-
import { map } from 'rxjs/operator/map';
22-
23-
const kBufferSize = 1;
24-
25-
export const firebaseAuthConfig = (config: AuthConfiguration): any => {
26-
return { provide: FirebaseAuthConfig, useValue: config }
27-
};
7+
import { observeOn } from 'rxjs/operator/observeOn';
8+
import { FirebaseApp } from '../app/index';
289

2910
@Injectable()
30-
export class AngularFireAuth extends ReplaySubject<FirebaseAuthState> {
31-
private _credentialCache: {[key:string]: any} = {};
32-
constructor(private _authBackend: AuthBackend,
33-
@Inject(WindowLocation) loc: any,
34-
@Optional() @Inject(FirebaseAuthConfig) private _config?: AuthConfiguration) {
35-
super(kBufferSize);
36-
37-
let firstPass = true;
38-
let onAuth = this._authBackend.onAuth();
39-
40-
mergeMap.call(onAuth, (authState: FirebaseAuthState) => {
41-
if (firstPass) {
42-
firstPass = false;
43-
if(['http:', 'https:'].indexOf(loc.protocol) > -1) {
44-
// Only call getRedirectResult() in a browser
45-
return map.call(this._authBackend.getRedirectResult(), (userCredential: firebase.auth.UserCredential) => {
46-
if (userCredential && userCredential.credential) {
47-
authState = attachCredentialToAuthState(authState, userCredential.credential, userCredential.credential.provider);
48-
this._credentialCache[userCredential.credential.provider] = userCredential.credential;
49-
}
50-
return authState;
51-
});
52-
}
53-
54-
}
55-
return observableOf(authState);
56-
})
57-
.subscribe((authData: FirebaseAuthState) => this._emitAuthData(authData));
58-
}
59-
60-
public login(config?: AuthConfiguration): firebase.Promise<FirebaseAuthState>;
61-
// If logging in with email and password
62-
public login(credentials?: EmailPasswordCredentials | firebase.auth.AuthCredential | string): firebase.Promise<FirebaseAuthState>;
63-
public login(credentials: EmailPasswordCredentials | firebase.auth.AuthCredential | string, config?: AuthConfiguration): firebase.Promise<FirebaseAuthState>;
64-
public login(obj1?: any, obj2?: AuthConfiguration): firebase.Promise<FirebaseAuthState> {
65-
let config: AuthConfiguration = null;
66-
let credentials: EmailPasswordCredentials | firebase.auth.AuthCredential | string = null;
67-
if (arguments.length > 2) {
68-
return this._reject('Login only accepts a maximum of two arguments.');
69-
} else if (arguments.length == 2) {
70-
credentials = obj1;
71-
config = obj2;
72-
} else if (arguments.length == 1) {
73-
// Check if obj1 is password credentials
74-
if (obj1.password && obj1.email) {
75-
credentials = obj1;
76-
config = {};
77-
} else {
78-
config = obj1;
79-
}
80-
}
81-
config = this._mergeConfigs(config);
82-
83-
if (utils.isNil(config.method)) {
84-
return this._reject('You must provide a login method');
85-
}
86-
let providerMethods = [AuthMethods.Popup, AuthMethods.Redirect, AuthMethods.OAuthToken];
87-
if (providerMethods.indexOf(config.method) != -1) {
88-
if (utils.isNil(config.provider)) {
89-
return this._reject('You must include a provider to use this auth method.');
90-
}
91-
}
92-
let credentialsMethods = [AuthMethods.Password, AuthMethods.OAuthToken, AuthMethods.CustomToken];
93-
if (credentialsMethods.indexOf(config.method) != -1) {
94-
if (!credentials) {
95-
return this._reject('You must include credentials to use this auth method.');
96-
}
97-
}
98-
99-
switch (config.method) {
100-
case AuthMethods.Popup:
101-
return this._authBackend.authWithOAuthPopup(config.provider, this._scrubConfig(config))
102-
.then((userCredential: firebase.auth.UserCredential) => {
103-
// Incorrect type information
104-
this._credentialCache[userCredential.credential.provider] = userCredential.credential;
105-
return authDataToAuthState(userCredential.user, (<any>userCredential).credential);
106-
});
107-
case AuthMethods.Redirect:
108-
// Gets around typings issue since this method doesn't resolve with a user.
109-
// The method really only does anything with an error, since it redirects.
110-
return <Promise<FirebaseAuthState>>(<any>this._authBackend).authWithOAuthRedirect(config.provider, this._scrubConfig(config));
111-
case AuthMethods.Anonymous:
112-
return this._authBackend.authAnonymously(this._scrubConfig(config));
113-
case AuthMethods.Password:
114-
return this._authBackend.authWithPassword(<EmailPasswordCredentials>credentials);
115-
case AuthMethods.OAuthToken:
116-
return this._authBackend.authWithOAuthToken(<firebase.auth.AuthCredential>credentials,
117-
this._scrubConfig(config));
118-
case AuthMethods.CustomToken:
119-
return this._authBackend.authWithCustomToken(<string>credentials);
120-
}
121-
}
122-
123-
public logout(): Promise<void> {
124-
return this._authBackend.unauth();
125-
}
126-
127-
public getAuth(): FirebaseAuthState {
128-
console.warn(`WARNING: the getAuth() API has changed behavior since adding support for Firebase 3.
129-
This will return null for the initial value when the page loads, even if the user is actually logged in.
130-
Please observe the actual authState asynchronously by subscribing to the auth service: af.auth.subscribe().
131-
The getAuth method will be removed in future releases`);
132-
return this._authBackend.getAuth()
133-
}
134-
135-
public createUser(credentials: EmailPasswordCredentials): firebase.Promise<FirebaseAuthState> {
136-
return this._authBackend.createUser(credentials);
137-
}
11+
export class AngularFireAuth {
13812

13913
/**
140-
* Merges the config object that is passed in with the configuration
141-
* provided through DI. Giving precendence to the one that was passed.
14+
* Firebase Auth instance
14215
*/
143-
private _mergeConfigs(config: AuthConfiguration): AuthConfiguration {
144-
if (this._config == null)
145-
return config;
146-
147-
return Object.assign({}, this._config, config);
148-
}
149-
150-
private _reject(msg: string): firebase.Promise<FirebaseAuthState> {
151-
return (<Promise<FirebaseAuthState>>new Promise((res, rej) => {
152-
return rej(msg);
153-
}));
154-
}
16+
auth: firebase.auth.Auth;
17+
18+
/**
19+
* Observable of authentication state
20+
*/
21+
authState: Observable<firebase.User>;
15522

156-
private _scrubConfig(config: AuthConfiguration, scrubProvider = true): any {
157-
let scrubbed = Object.assign({}, config);
158-
if (scrubProvider) {
159-
delete scrubbed.provider;
160-
}
161-
delete scrubbed.method;
162-
return scrubbed;
23+
constructor(public app: FirebaseApp) {
24+
this.authState = FirebaseAuthStateObservable(app);
16325
}
16426

165-
166-
private _emitAuthData(authData: FirebaseAuthState): void {
167-
if (authData == null) {
168-
this.next(null);
169-
} else {
170-
if (authData.auth && authData.auth.providerData && authData.auth.providerData[0]) {
171-
let providerId = authData.auth.providerData[0].providerId;
172-
let providerCredential = this._credentialCache[providerId];
173-
if (providerCredential) {
174-
authData = attachCredentialToAuthState(authData, providerCredential, providerId);
175-
}
176-
}
177-
178-
this.next(authData);
179-
}
180-
}
18127
}
18228

183-
function attachCredentialToAuthState (authState: FirebaseAuthState, credential, providerId: string): FirebaseAuthState {
184-
if (!authState) return authState;
185-
// TODO make authState immutable
186-
authState[stripProviderId(providerId)] = credential;
187-
return authState;
29+
/**
30+
* Create an Observable of Firebase authentication state. Each event is called
31+
* within the current zone.
32+
* @param app - Firebase App instance
33+
*/
34+
export function FirebaseAuthStateObservable(app: FirebaseApp) {
35+
const authState = Observable.create(firebase.auth().onAuthStateChanged);
36+
return observeOn.call(authState, new utils.ZoneScheduler(Zone.current));
18837
}

‎src/database/database.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { FirebaseListObservable, FirebaseObjectObservable, FirebaseObjectFactory
1010
@Injectable()
1111
export class AngularFireDatabase {
1212

13-
constructor(private app: FirebaseApp) {}
13+
constructor(public app: FirebaseApp) {}
1414

1515
list(pathOrRef: PathReference, opts?:FirebaseListFactoryOpts):FirebaseListObservable<any[]> {
1616
const ref = utils.getRef(this.app, pathOrRef);

‎src/interfaces.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,5 @@ export type DatabaseSnapshot = firebase.database.DataSnapshot;
9393
export type DatabaseReference = firebase.database.Reference;
9494
export type DatabaseQuery = firebase.database.Query;
9595
export type QueryReference = DatabaseReference | DatabaseQuery;
96-
export type PathReference = QueryReference | string;
96+
export type PathReference = QueryReference | string;
97+
export type Auth = firebase.auth.Auth;

0 commit comments

Comments
 (0)