0

I am trying to use authgaurd in angular 4 to limit access to the website based on the userid of the person trying to access it. This is running on a Intranet and all users will be domain users authenticated by microsoft active directory.

My application is running on a linux machine using apache tomcat. In order of the authguard to function the canActivate method will need to first call a IIS webservice to retrieve the current user's ID. This ID will be based to the application to verify the user's account and determine their role in the system.

I have been able to have one subscription call the next subscription and can retrieve the data but I do not know how to implement this in such a way has to have the final boolean passed back to the canActivate method. The canActivate code below just makes the Http call and moves on. What is the correct way to make it wait on the results.

@Injectable()
export class OnlyKnownUsersGuard implements CanActivate {

  private isKnownUser: boolean;
  private alreadyChecked = false;

  constructor(private employeeService: EmployeeService, private httpService: HttpService) { }


  canActivate(): Observable<boolean> | Promise<boolean> | boolean {
      if ( ! this.alreadyChecked  ) {
         this.httpService.getLoggedInUser().subscribe(
                  (data: string) => this.onGetEmpInfo(data) );
          this.alreadyChecked = true;
       }
      return this.isKnownUser;
  }


  onGetEmpInfo( userId: string)  {
      this.employeeService.loadEmployeeByUserId(userId).subscribe(
          (employee: Employee) => this.isEmployeeFound(employee) ) ;
  }

  isEmployeeFound(employee: Employee)  {
      if ( employee instanceof Object ) {
          this.isKnownUser = true;
      } else {
          this.isKnownUser = false;
      }

  }

}
Joe
  • 43
  • 1
  • 5
  • 1
    If you want it to wait you need to return an observable (or promise), as the signature suggests. Try chaining `.map` to transform the API response down to the Boolean you need. – jonrsharpe Sep 28 '17 at 12:54
  • I had tried that but I was getting back an syntax error. I think the exact error was that an Observable> is not an Observable. I could not come up with the correct syntax. – Joe Sep 28 '17 at 16:02
  • It sounds like you need a `flatMap` to unroll `O>` to `O`, but without a [mcve] that’s all I can say. – jonrsharpe Sep 28 '17 at 16:04

1 Answers1

0

flatMap was the answer and the syntax for the above code changed to this.

@Injectable()
export class OnlyKnownUsersGuard implements CanActivate {

  private isKnownUser: boolean;
  private alreadyChecked = false;

  constructor(private employeeService: EmployeeService, private httpService: HttpService) { }


  canActivate(): Observable<boolean> | Promise<boolean> | boolean {
      if ( ! this.alreadyChecked  ) {
         this.httpService.getLoggedInUser().flatMap(
              (data: string) => this.onGetEmpInfo(data) );
      }
      else {   
          return this.isKnownUser;
      }
  }


  onGetEmpInfo( userId: string)  {
      this.employeeService.loadEmployeeByUserId(userId).map(
          (employee: Employee) => this.isEmployeeFound(employee) ) ;
  }

  isEmployeeFound(employee: Employee)  {
      if ( employee instanceof Object ) {
          this.isKnownUser = true;
      } else {
          this.isKnownUser = false;
      }
      this.alreadyChecked = true;
      return this.isKnownUser;
  }

}
Joe
  • 43
  • 1
  • 5