- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我已经使用 Firebase 身份验证和 Cloud Fire Store 建立了一个新的 Angular 6 项目。有一个登录页面,您可以在其中通过谷歌登录,用户数据保存在 Firestore 中(代码如下)。我唯一的问题是如何检查用户是否已经登录,有什么最佳做法吗?
目前我正在异步获取用户数据,但随后导航开始闪烁。一秒钟有登录按钮,然后切换到注销按钮。在呈现页面之前是否有检查登录状态的好方法?
User.ts
export interface User {
uid: string;
email: string;
}
auth.service.ts
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import * as firebase from 'firebase/app';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFirestore, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { User } from './user';
@Injectable({
providedIn: 'root'
})
export class AuthService {
user: Observable<User>;
constructor(private afAuth: AngularFireAuth, private afs: AngularFirestore, private router: Router) {
this.user = this.afAuth.authState.pipe(
switchMap(user => {
if (user) {
return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
}
}))
}
public googleLogin() {
const provider = new firebase.auth.GoogleAuthProvider()
return this.oAuthLogin(provider);
}
public signOut() {
this.afAuth.auth.signOut();
}
private oAuthLogin(provider) {
return this.afAuth.auth.signInWithPopup(provider)
.then((credential) => {
this.updateUserData(credential.user)
})
}
private updateUserData(user) {
const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.uid}`);
const data: User = {
uid: user.uid,
email: user.email
}
return userRef.set(data, { merge: true })
}
}
navigation.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../core/auth.service';
import { AngularFireAuth } from 'angularfire2/auth';
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss']
})
export class NavigationComponent implements OnInit {
constructor(public auth: AuthService) { }
ngOnInit() {}
auth.service.ts
<div *ngIf="auth.user | async; then loggedIn else loggedOut"></div>
<ng-template #loggedOut>
<li class="nav-item d-none d-md-inline-block pl-2 pr-0">
<a class="btn btn-sm btn-primary u-btn-primary u-btn-pill transition-3d-hover" href="/login">
Login
</a>
</li>
</ng-template>
<ng-template #loggedIn>
<li class="nav-item d-none d-md-inline-block pl-2 pr-0">
<a class="btn btn-sm btn-primary u-btn-primary u-btn-pill transition-3d-hover" (click)="auth.signOut()">
Logout
</a>
</li>
</ng-template>
最佳答案
您可能很久以前就明白了这一点,但其他人可能会疑惑。我选择检查 angularFireAuth 的 authState。如果它为空,则您已注销。然后您可以按照 Ryan Chenkie's Medium article 中的说明使用路由守卫
@Injectable()
export class FirebaseAuthService {
private authState: Observable<firebase.User>
private currentUser: firebase.User = null;
constructor(
public afAuth: AngularFireAuth,
private http: HttpClient,
private localStorage: LocalStorageService,
private router: Router,
private snackBar: MatSnackBar) {
this.authState = this.afAuth.authState;
this.authState.subscribe(user => {
if (user) {
this.currentUser = user;
this.localStorage.storeSimple('userData', user)
this.openSnackBar('Successfully authenticated');
console.log('AUTHSTATE USER', user)
this.router.navigate(['home']);
} else {
console.log('AUTHSTATE USER EMPTY', user)
this.currentUser = null;
}
},
err => {
this.openSnackBar(`${err.status} ${err.statusText} (${err.error.message})`, 'Please try again')
});
}
isAuthenticated(): boolean {
return this.authState !== null;
}
loginEmail(email, password, route) {
this.afAuth.auth.signInWithEmailAndPassword(email, password).catch(error => {
let errorCode = error.code;
let errorMessage = error.message;
this.openSnackBar(error, 'OK')
});
}
logout() {
this.afAuth.auth.signOut()
.then(response => this.openSnackBar('Signed out'))
.catch(error => this.openSnackBar('Error signing out: ' + error));
}
...
}
关于javascript - Angular 6 AngularFireAuth 检查用户是否在页面呈现之前登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50572683/
我正在寻找一种使此打印 HTML 代码 fragment 向后兼容旧 Android 版本的简单方法: @TargetApi(Build.VERSION_CODES.KITKAT) private v
我在 GCC 终端 (centos linux) 中为 ATM 项目编译以下 c 和 .h 代码时收到以下错误。请帮忙,因为我是编程新手。 validate_acc.h #ifndef _VALIDA
在写关于 SO 的不同问题的答案时,我制作了这个片段: @import url('https://fonts.googleapis.com/css?family=Shadows+Into+Light'
试图弄清楚我应该如何在 my_div_class 之前放置一个 span 而不是替换所有它。现在它取代了 div,但我不想这样做。我假设它类似于 :before 但不知道如何使用它。 { va
我正在使用选择库 http://github.hubspot.com/select/和 noUiSlider https://refreshless.com/nouislider/ .我面临的问题如下
我是开发新手,独自工作。我正在使用 Xcode 和 git 版本控制。可能我没有适本地组织和做错事,但我通常决定做 promise 只是为了在我破坏一切之前做出安全点。在那一刻,我发现很难恰本地描述我
我想确保在同一个桶和键上读取和写入时,应该更新获取的值,也就是说,应该在对其进行写入操作之后获取它。我怎样才能做到这一点? 我想要的是,如果我更新一个键的值,如果我同时使用不同线程获取值,则更新同一个
我的问题与this有关问题,已经有了答案: yes, there is a happens-before relationship imposed between actionsof the thre
The before and after hook documentation on Relish仅显示 before(:suite) 在 before(:all) 之前调用。 我什么时候应该使用其中
我有 CSV 行,我想在其中检测所有内部双引号,没有文本限定符。这几乎可以正常工作,但我的正则表达式还可以检测双引号后的字符。 CSV 部分: "7580";"Lorem ipsum";"";"Lor
是否可以通过Youtube数据API检查广告是否可以与特定视频一起显示? 我了解contentDetails.licensedContent仅显示视频是否已上传至同一伙伴然后由其声明版权。由于第三者权
考虑一下用漂亮的彩色图表描述的“像素管道” https://developers.google.com/web/fundamentals/performance/rendering/ 我有一个元素(比
之前?
在 MVC3 中,我可以轻松地将 jQuery 脚本标签移动到页面底部“_Layout.vbhtml” 但是,在 ASP.NET MVC3 中,当您使用编辑器模板创建 Controller 时,脚手
悬停时内容被替换,但是当鼠标离开元素时我希望它变回来。我该怎么做? $('.img-wrap').hover(function(){ $(this).find('h4').text('Go
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 已关闭 9 年前。 有关您编写的代码问题的问题必须在问题本身中描述具体问题 - 并包含有效代码以重现该问题。
版本:qwt 6.0.1我尝试开发频谱的对数缩放。我使用简单的线条来启用缩放plotspectrum->setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10S
我有两个相同的表,I_Subject 和 I_Temp_Subject,我想将 Temp_Subject 表复制到 Subject 表。 I_Temp_Subject 由简单用户使用,I_Subjec
我的印象是第一次绘制发生在触发 DOMContentLoaded 事件之后。特别是,因为我认为为了让第一次绘制发生,需要渲染树,它依赖于 DOM 构造。另外,我知道 DOM 构造完成时会触发 DOMC
我是一名优秀的程序员,十分优秀!