Каков наилучший способ сделать маршрутизацию угловых компонентов, используя node.js в качестве бэкэнда - PullRequest
0 голосов
/ 31 марта 2019

Я пытаюсь перемещаться по угловым компонентам (регистрация и панель инструментов). Если пользователь уже зарегистрировался, его следует перенаправить на компонент панели мониторинга, а если нет - на компонент регистрации. Запуск только файла lib.js в качестве сервера. Угловые файлы развертываются после использования команды ng build (с использованием папки dist). И интерфейс, и фон находятся в одной папке

Вот некоторые фрагменты кода:

lib.js (внутренний файл node.js)

app.use(exp.static(path.join(__dirname, 'dist')));

app.listen(PORT, function() {
    console.log('Express server listening on port ', PORT); // eslint-disable-line
});

app.post('/check_account',function(req,res){
    console.log(req.body);
    connection.query('SELECT * FROM login_table WHERE m_pub_key LIKE '+'\"'+req.body.m_pub_key+'\"' ,function(error,rows,fields){
        if(!!error){
            console.log('error!');
            res.send('Error!');
        }
        else
            {
                console.log(rows);
                if(rows.length!=0){
                    data={
                        is_signed_up: 1
                    }
                    res.send(data);
                }
                else{
                    data={
                        is_signed_up: 0
                    }
                    res.send(data);
                }
            }
    });

});

app.get('/dashboard',function(req,res){
    console.log("inside dashboard backend");
    res.sendFile(path.join(__dirname, 'dist/index.html'));
});

app.get('/signup', function (req,res) {
    console.log("signup backend");
    res.sendFile(path.join(__dirname, 'dist/index.html'));
});

app.get('/', function (req,res) {
    console.log("slash backend");
    res.sendFile(path.join(__dirname, 'dist/index.html'));
});

app.component.ts

  constructor(private router: Router,private _appService: AppService, private zone: NgZone, private http: HttpClient, private route: ActivatedRoute){
    console.log("inside app component constructor");
    this.checkAndInstantiateWeb3();
    this.onReady();

  }

  checkAccount(){
    let data_send = JSON.stringify({
            'm_pub_key': this.m_pub_key
        });

      this.zone.runOutsideAngular(()=>{
        this._appService.post_method(this.url+"check_account", data_send).subscribe(
          data => {
              this.is_signed_up=data["is_signed_up"];
              console.log(this.is_signed_up+"***************8");
              if(this.is_signed_up==1){
                console.log("navigating to dash");
                this.router.navigate(['/dashboard']);
                //this.http.get("/dashboard");
              }
              else{
                console.log("navigating to signuo");
                this.router.navigate(['/signup']);
                //this.http.get("/signup");
              }
          },
          error => {
              // console.log('post error');
          });
});
  }

  public checkAndInstantiateWeb3 = () => {
        if (typeof window.web3 !== 'undefined') {
            console.warn('Using injected web3');
            this.web3 = new Web3(window.web3.currentProvider);
        } else {
            // when running in browser, use incognito mode or log out of metamask
            console.warn('No web 3 detected, falling back to Ganache');
            this.provider = new Web3.providers.HttpProvider('http://localhost:7545');
            this.web3 = new Web3(this.provider);
        }
        window.ethereum.enable();
      }

  public onReady = () => {
        // get initial account balance so it can be displayed
        this.web3.eth.getAccounts((err, accs) => {
          if (err != null) {
            console.log(err);
            alert('There was an error fetching your accounts.');
            return;
          }

          if (accs.length === 0) {
            alert('You are not connected to an Ethereum client.');
            return;
          }
          this.m_pub_key=accs[0];
          console.log(this.m_pub_key);
          this.checkAccount();
        });
      }
}

приложение-routing.module.ts

const routes: Routes = [
    { path: 'signup', component: SignupComponent },
    { path: '', pathMatch: 'full', redirectTo: 'signup' },
    { path: 'dashboard', component: DashboardComponent },
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule],
})
export class AppRoutingModule { }

Теперь проблема в том, что если пользователь уже зарегистрировался, а затем, когда он пытается перейти на любую страницу, он перенаправляется на первую страницу регистрации, а затем на страницу панели мониторинга, но обе страницы перекрываются, а также компонент панели мониторинга не работает. должным образом. Когда пользователь напрямую переходит к компоненту панели мониторинга с помощью URL-адреса, компонент панели мониторинга работает, как ожидается. Буду признателен за любую помощь в этой проблеме.

РЕДАКТИРОВАТЬ 1

После ответа "k0hamed". Использование атрибута canActivate как это { path: 'signup', component: SignupComponent, canActivate:[AuthGuard] } Это файлы защиты и обслуживания, которые я создал, и они не работают должным образом. val в файле auth.guard.ts не изменяется и ничего не загружается, когда я захожу на localhost: 8080 / или localhost: 8080 / signup, но компонент панели мониторинга загружается, когда я набираю localhost: 8080 / dashboard

auth.guard.ts:

export class AuthGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
    ): Observable<boolean> {
    console.log('AuthGuard#canActivate called');
    return this.signupService.onReady()
             .pipe(tap(val=>!val && this.router.navigate(['/signup'])));
  }
  constructor(private signupService: AuthService, private router: Router) {}
}

auth.service.ts:

export class AuthService {

    provider: any;
    account: any;
    accounts: any;
    web3: any;
    m_pub_key="";
    title = 'project2';
    is_signed_up:any;
    url = "http://localhost:8080/";
    val = of(false);

    constructor(private _appService: AppService, private zone: NgZone, private router: Router){
    }

    onReady():Observable<boolean> {
        // get initial account balance so it can be displayed
        // (async () => {
        if (typeof window.web3 !== 'undefined') {
            console.warn('Using injected web3');
            this.web3 = new Web3(window.web3.currentProvider);
        } else {
            // when running in browser, use incognito mode or log out of metamask
            console.warn('No web 3 detected, falling back to Ganache');
            this.provider = new Web3.providers.HttpProvider('http://localhost:7545');
            this.web3 = new Web3(this.provider);
        }
        window.ethereum.enable();


        this.web3.eth.getAccounts((err, accs) => {
          if (err != null) {
            console.log(err);
            alert('There was an error fetching your accounts.');
            return;
          }

          if (accs.length === 0) {
            alert('You are not connected to an Ethereum client.');
            return;
          }
          this.m_pub_key=accs[0];
          console.log(this.m_pub_key);
          // this.isSigned();
        });

        let data_send = JSON.stringify({
            'm_pub_key': this.m_pub_key
        });
            this._appService.post_method(this.url+"check_account", data_send).subscribe(
              data => {
                  this.is_signed_up=data["is_signed_up"];
                  console.log(this.is_signed_up+"***************8");
                  if(this.is_signed_up==1){
                    console.log("navigating to dash");
                    //this.router.navigate(['/dashboard']);
                    //this.http.get("/dashboard");
                    this.val = of(false);
                    // this.router.navigate(['/dashboard']);
                  }
                  else{
                    console.log("navigating to signup");
                    //this.router.navigate(['/signup']);
                    //this.http.get("/signup");
                    this.val = of(true);
                    // this.router.navigate(['/signup']);
                  }
                  console.log(this.val);
              },
                    // console.log(this.val);
              error => {
                  // console.log('post error');
              });
        // });
        console.log(this.val);
        return this.val
      }
}

1 Ответ

0 голосов
/ 31 марта 2019

первый из

вы не должны обрабатывать буквально каждый маршрут в бэк-энде, если angular делает это

app.get('/*', function(req,res) {
  res.sendFile(path.join( __dirname + '/dist/index.html'));
});

добавление этого параметра в качестве последнего маршрута в вашем экспресс-приложении будет перенаправлять каждыйзапрос не обрабатывается выше углового и angular будет использовать свой собственный маршрутизатор

секунда, вам нужно использовать canActive guard для вашего варианта использования и перенести проверкуФункция внутри него, если пользователь не подписан, он будет перенаправлен на страницу signup, иначе он позволит ему пройти, что-то вроде:

@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> {
    console.log('AuthGuard#canActivate called');
    return this.signupService.isSigned()
             .pipe(tap(val => !val && this.router.navigate(['/signup']))); // Navigate to signup when it returns false
  }
  constructor(private signupService: SignupService, private router: Router) {}
}

В то время как SignupService является службой с методом isSigned()которые возвращают Observable<boolean>;

Возможно, вам понадобится создать еще одну защиту для маршрута страницы signup, чтобы проверить, не подписано ли и перенаправить ли на панель мониторинга в противном случае.

ОБНОВЛЕНИЕ: Вам необходимоили превратить весь ваш код в обещания или наблюдаемые, чтобы обрабатывать асинхронные функции, когда охранники принимают наблюдаемые и обещания

Так, например, чтобы использовать способ наблюдения, вам нужно повернуть getAcounts функцию to возвращать наблюдаемый вместо зависимости от обратного вызова, к счастью, rxJs имеет встроенную функцию, поэтому bindNodeCallback вы можете просто сделать

const getAccountsAsObservable = bindNodeCallback(
    callback => this.web3.eth.getAccounts(callback));

, теперь вы можете использовать магию rxJs для цепочкикод через каналы, и вам нужно обработать ошибку с pipe также и заставить ее возвращать наблюдаемое значение false.

и ваш сервис будет выглядеть примерно так:

onReady():Observable<boolean> {
  // ..
  const getAccountsAsObservable = Observable.bindNodeCallback(
    callback => this.web3.eth.getAccounts(callback));

  return getAccountsAsObservable()
    .pipe(
      switchMap(acc => {
        if (accs.length === 0) {
          alert('You are not connected to an Ethereum client.');
          // throw an error to skip to "cathError" pipe
          return throwError(new Error('You are not connected to an Ethereum client.'));
        }
        const m_pub_key=accs[0];
        console.log(this.m_pub_key);
        const data_send = JSON.stringify({
          'm_pub_key': m_pub_key
        });
        return of(data_send);
      }),
      switchMap(data_send => { 
        this._appService.post_method(this.url+"check_account", data_send)
      }),
      map(data => {
        this.is_signed_up=data["is_signed_up"];
        console.log(this.is_signed_up+"***************8");
        if(this.is_signed_up==1){
          console.log("navigating to dash");
          //this.router.navigate(['/dashboard']);
          //this.http.get("/dashboard");
          return false;
          // this.router.navigate(['/dashboard']);
        } else {
          console.log("navigating to signup");
          //this.router.navigate(['/signup']);
          //this.http.get("/signup");
          return true;
          // this.router.navigate(['/signup']);
        }
      }),
      catchError(err => {
        //handle error of getAccounts or post_method here
        console.log(err);
        alert('There was an error fetching your accounts.');
        return of(false);
      })
    )
}

вы можете превратить все это в обещания и / или использовать async / await, вы можете включить _appService.post_method для обещания с .pipe(take(1)).toPromise

...