简体   繁体   English

Angular 4 canActivate与嵌套可观察对象不起作用

[英]Angular 4 canActivate with nested observables not working

First off sorry for the title, I had no idea what to call this. 首先,对不起标题,我不知道该怎么称呼。

I am working on a project that requires an authentication guard which I originally had working great. 我正在从事一个需要身份验证保护的项目,而我本来就很出色。 Bascially all it did was check to see if there was a valid token in local storage. 基本上,它所做的只是检查本地存储中是否存在有效令牌。 Pretty simple. 很简单

Well as most Apps do, it got a little more complicated in the form of needing to set a "Reset Password" flag on the users profile which would force them to reset their password on the next login. 就像大多数Apps一样,它变得有点复杂,需要在用户个人资料上设置“重置密码”标志,这会迫使他们在下次登录时重置密码。 That's where the guard stopped working as expected. 那是守卫按预期停止工作的地方。 I think that the return Observable.of(true) isn't quite making up the chain, because when the guard runs the console logs PASSWORD RESET, PROCEED , but fails to allow the user to continue. 我认为return Observable.of(true)并不是很完整,因为当防护程序运行时,控制台会记录PASSWORD RESET, PROCEED ,但无法允许用户继续。 I am not well versed enough with RxJs to know what needs to be done. 我对RxJ并不十分了解,需要知道需要做什么。 Also I apologize in advance for the observable pyramid of doom. 我还要为可观的厄运金字塔表示歉意。 Refactoring that is something on the "would be nice to do" list. 重构就是“很乐意做”列表中的内容。

@Injectable()

export class AuthenticationGuard implements CanActivate {

constructor(
    private _Router: Router,
    private _LocalUserService: LocalUserService,
    private _SystemSettingsService: SystemSettingsService,
    private _UsersService: UsersService
) { }

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {

    return this._SystemSettingsService.getSystemSetting('AUTHENTICATION')
        .map(_SystemSetting => {

            // Check for Authentication to be Enabled
            if (_SystemSetting.data.settingValue.enabled) {

                // Check for an Authentication Token Locally
                this._LocalUserService.getLocalUserObject()
                    .subscribe(_LocalUserObject => {

                        // Check if Local User Object is Empty and if a Token is Present
                        if (_LocalUserObject && _LocalUserObject.token) {

                            // Retrieve the user that the token is associated to from API
                            this._UsersService.getUser(_LocalUserObject.userID)
                                .subscribe(_User => {

                                    // If password reset is enabled, force user to reset their password.
                                    if (_User.data.userPasswordReset) {
                                        this._Router.navigate(['/gateway/password-reset']);
                                        return Observable.of(false);

                                        // If password reset is false, allow the user to proceed.
                                    } else {
                                        console.log('PASSWORD RESET, PROCEED');
                                        return Observable.of(true);
                                    }
                                })

                            // If Local User Object is invalid, navigate to Login Page.
                        } else {
                            // not logged in so redirect to login page with the return url
                            this._Router.navigate(['/gateway/login'], { queryParams: { returnUrl: state.url } });
                            return Observable.of(false);
                        }
                    })

                // If Athentication is disabled allow the user to bypass authentication
            } else {
                return Observable.of(true);
            }
        })
    }
}

Any suggestions would be much appreciated... Thanks 任何建议将不胜感激...谢谢

I ended up figuring it out. 我最终弄清楚了。 I started by consolidating most of the observables into a single call. 我首先将大多数可观察对象合并为一个调用。 I still have one nested observable. 我仍然有一个嵌套可观察的。 But I also found out that you have to mindful of your return type. 但我还发现,您必须注意返回类型。 Within the switchMap I am returning Observables, however within the nested map operation it switches to boolean. 在switchMap中,我将返回Observables,但是在嵌套映射操作中,它将切换为boolean。

 @Injectable() export class AuthenticationGuard implements OnInit, CanActivate { systemSetting$: Observable<any> = this._SystemSettingsService.getSystemSetting('AUTHENTICATION'); localUserObject$: Observable<LocalUserObject> = this._LocalUserService.getLocalUserObject(); initialData = Observable.zip( this.systemSetting$, this.localUserObject$ ); constructor( private _Router: Router, private _LocalUserService: LocalUserService, private _SystemSettingsService: SystemSettingsService, private _UsersService: UsersService ) { } ngOnInit() { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { return this.initialData.switchMap(_Result => { // Check for Authentication to be Enabled if (_Result[0].data.settingValue.enabled) { // Check if Local User Object is Empty and if a Token is Present if (_Result[1] && _Result[1].token) { return this._UsersService.getUser(_Result[1].userID) .map(_User => { // If password reset is enabled, force user to reset their password. if (_User.data.userPasswordReset) { this._Router.navigate(['/gateway/password-reset']); return false; // If password reset is false, allow the user to proceed. } else { console.log('PASSWORD RESET, PROCEED'); return true; } }) // If Local User Object is invalid, navigate to Login Page. } else { // not logged in so redirect to login page with the return url this._Router.navigate(['/gateway/login'], { queryParams: { returnUrl: state.url } }); return Observable.of(false); } // If Authentication is disabled allow the user to bypass authentication } else { return Observable.of(true); } }) } } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM