我在下面的提供者处留下了我的登录实现。
虽然我还没有在这个项目中迁移到 Modular Firebase V9,但身份验证持久性仍然有效——登录过一次的用户不需要每次回来都重新登录。
我发现将身份验证逻辑保留在可以注入组件或模块的服务中是一种很好的做法。
在构造函数中,您可以找到一种很好的方法来确定您的用户是否已登录并在 Cloud Firestore 中拥有与他们的身份验证 ID 关联的个人资料。
export class AuthService {
analytics = firebase.analytics(); // this declaration works better than constructor init from import
userCredential; // to store the promise returned when signing up/ in with email & password
// type: User from the model
user$: Observable<User>; // defined as observable as it can change when user signs in/out
constructor(
// inject imports for fire store auth service in constructor
private afAuth: AngularFireAuth,
private afs: AngularFirestore,
private router: Router
) {
// Get the auth state, then fetch the Firestore user document or return null
this.user$ = this.afAuth.authState.pipe( // define the observable state
switchMap(user => {
// Logged in
if (user) { // if user is defined
// point to document with matching ID
return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
} else {
// Logged out
return of(null); // allows us to tell when user is not logged in
}
})
);
}
/**
* Authenticate users with Google O-Auth provider
* @param {boolean=} [registration = false] - whether this is the first sign in or not
*/
async googleSignIn(registration: boolean = false) {
// reference google auth provider
const provider = new auth.GoogleAuthProvider();
// pass provider to sign in with popup functionality
this.userCredential = await this.afAuth.signInWithPopup(provider);
if (registration) { // if the request is coming from the registration page
try {
await this.insertNewUser(this.userCredential.user, this.userCredential.user.displayName);
await this.verifyEmail(); // send a verification email to the user when registering
await this.router.navigate(['/user-profile']);
} catch (err) {
console.log(`Error: ${err.errorMessage}`);
M.toast({html: `Error: ${err.errorMessage}`, classes: 'rounded materialize-red'});
}
} else { // user is logging in again
try {
await this.router.navigate(['/user-profile']);
M.toast({html: `Signed in as ${this.userCredential.user.displayName}`, classes: 'rounded blue'});
// let user know that they haven't been verified
if (!this.userCredential.emailVerified) {
console.log(`user's email has not been verified`);
M.toast({
html: `Your email has not yet been verified. Please check your inbox.`,
classes: 'rounded orange darken-2'
});
}
} catch (err) {
console.log(`Error: ${err.errorMessage}`);
M.toast({html: `Error: ${err.errorMessage}`, classes: 'rounded materialize-red'});
}
}
// track the login event with analytics
this.analytics.logEvent('login', {serviceName: 'Google Login'});
} // end of sign in function
} // end of auth service