2

I'm pretty new to Angular..

I have a AuthService in my web app that authenticate users via Angularfire2 (firebase) and insert the email and a flag (indicating whether user filled the profile data form) into a firebase database.

My route guard checks whether the user is authenticated and whether user filled in the the profile data form if not, i redirect to the profile data form. If the user already completed the form, i re direct to hope page.

I obtain whether the user completed the basic data form via UserData service:

  constructor(private afd: AngularFireDatabase, private authService: AuthService) {

  }

  isProfileComplete (): Observable<any> {
    return this.afd.list(`/users/${this.authService.uid}`)
            .snapshotChanges()

  }

Then in the authGuard i do the logic to direct the user:

 constructor(private authService: AuthService,
              private router: Router,
              private usrData: UserDataService) {}

  canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

    if (this.authService.isAuthenticated())  {
      console.log(this.usrData.isProfileComplete())
      this.usrData.isProfileComplete()
      .map(userInfos => {
        console.log(userInfos)
           userInfos.forEach(item => {
            console.log(userInfos)
            if ((item.payload.key === 'profileComplete') && (item.payload.val() === true)) {
              console.log('user is logged in & data form completed')
              return true;
            } else if ((item.payload.key === 'profileComplete') && (item.payload.val() !== true)) {
              this.router.navigate(['data_form']);
              console.log('user logged in not completed the form')
              return false;
            }
      })

      })

    }  else {
        this.router.navigate(['login']);
        console.log('user is not logged in ')
        return false;
    }
}

I think the code is not reaching the map section of the observable to read the values for the key profileComplete

Could someone kindly point me at the right direction please?

Thank you

sheeni
  • 377
  • 1
  • 17

2 Answers2

0

You should return this type Observable<boolean> | Promise<boolean> from CanActivate. Because JavaScript not wait callbacks. Example:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {

if (this.authService.isAuthenticated()) {
  console.log(this.usrData.isProfileComplete())
  return this.usrData.isProfileComplete()
    .map(userInfos => {
      console.log(userInfos)
      userInfos.forEach(item => {
        console.log(userInfos)
        if ((item.payload.key === 'profileComplete') && (item.payload.val() === true)) {
          console.log('user is logged in & data form completed')
          return of(true);
        } else if ((item.payload.key === 'profileComplete') && (item.payload.val() !== true)) {
          this.router.navigate(['data_form']);
          console.log('user logged in not completed the form')
          return of(false);
        }
      })

    })

} else {
  this.router.navigate(['login']);
  console.log('user is not logged in ')
  return of(false);
}

}

Abylay
  • 344
  • 2
  • 11
0

Does the following return an Observable?

this.usrData.isProfileComplete()

Regardless, you're returning true / false from within the context of your forEach loop, which means the outer map method isn't returning anything.

You might want to consider using a find rather than a forEach, then you can return the result of whether the find found anything:

return !!userInfos.find(item => (item.payload.key === 'profileComplete') 
                                && (item.payload.val() === true));

Obviously this doesn't handle you redirection case where you want to head back to the form, but should point you in the right direction

Chris White
  • 29,949
  • 4
  • 71
  • 93
  • Hi Chris, thank you for the response. Unfortunately it looks like the code isn't reaching the item (!!userInfos.find(item => ) when running. i added a console.log just above the return and there was no output. re:this.usrData.isProfileComplete() yes it returns a Observable i have added the code bend it above too. – sheeni May 11 '18 at 07:33
  • you also need the return keyword on your map statement. – Chris White May 11 '18 at 13:22
  • perfect, Thank you – sheeni May 11 '18 at 13:34