Angular - login em dois componentes - resolvido

11 respostas Resolvido
G

Hoje o sistema chama a página de login por dois componentes.

Como o componente de login é um modal.

Em cada uma dás páginas tem uma variavel logado que é boolean, para esconder ou aparecer componentes

Eu logo, mas só ajusta, quando aperto F5. Como fazer para funcionar normalmente ?

11 Respostas

R

salva no localStorage, depois verifica se o user ta logado ou nao

G

Sim está em localStorage

AccountService

import { Injectable } from '@angular/core';
import { LocalStorageService, SessionStorageService } from 'ngx-webstorage';
import { ReplaySubject } from 'rxjs';
import { UsuarioLogadoModel } from '../model/usuario-logado.model';
@Injectable({ providedIn: 'root' })
export class AccountService {
  private usuarioLogado: UsuarioLogadoModel | null = null;
  private authenticationState = new ReplaySubject<UsuarioLogadoModel | null>(1);
  constructor(
    private localStorage: LocalStorageService,
    private sessionStorage: SessionStorageService
  ) {}
  authenticate(usuarioLogado: UsuarioLogadoModel | null): void {
    this.usuarioLogado = usuarioLogado;
    this.authenticationState.next(this.usuarioLogado);
  }
  isAuthenticated(): boolean {
    return (
      this.localStorage.retrieve('authentication_token') ||
      this.sessionStorage.retrieve('authentication_token')
    );
  }
}

Componente my-header.component

import { Component, OnInit } from '@angular/core';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { AccountService } from 'src/app/core/auth/account.service';
import { AppConfirmService } from 'src/app/core/service/app-confirm/app-confirm.service';
import { LoginService } from 'src/app/core/service/login.service';
import { AlterarUsuarioLogadoComponent } from '../modal/alterar/alterar-usuario-logado.component';
import { ExtratoComponent } from '../modal/extrato/extrato.component';
import { LoginComponent } from '../modal/login/login.component';
import { NotaFiscalComponent } from '../modal/nota-fiscal/nota-fiscal.component';

@Component({
  selector: 'app-my-header',
  templateUrl: './my-header.component.html',
  styleUrls: ['./my-header.component.scss'],
})
export class MyHeaderComponent implements OnInit {
  menuState: boolean = false;
  logado: boolean;
  showNavigationIndicators = false;
  constructor(
    private confirmService: AppConfirmService,
    private loginService: LoginService,
    private dialog: MatDialog,
    private router: Router,
    private accountService: AccountService
  ) {
    this.logado = false;
  }
  async ngOnInit() {
    this.logado = await this.accountService.isAuthenticated();
  }
  meuPerfil(): void {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.autoFocus = true;
    dialogConfig.width = '600px';
    this.dialog.open(AlterarUsuarioLogadoComponent, dialogConfig);
  }
  extrato(): void {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.autoFocus = true;
    dialogConfig.width = '405px';
    this.dialog.open(ExtratoComponent, dialogConfig);
  }
  notaFiscal(): void {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.autoFocus = true;
    dialogConfig.width = '405px';
    dialogConfig.height = '580px';
    this.dialog.open(NotaFiscalComponent, dialogConfig);
  }
  logout(): void {
    this.confirmService
      .confirm({
        title: 'Sair',
        message: 'Deseja sair do sistema ?',
      })
      .subscribe(async (res) => {
        if (!res) {
          return;
        } else {
          this.logado = false;
          this.loginService.logout();
        }
      });
  }
  showMenu(): void {
    this.menuState = !this.menuState;
  }
  getMenuState(): boolean {
    return this.menuState;
  }
  async reward() {
    this.logado = this.accountService.isAuthenticated();
    if (!this.logado) {
      this.login();
    } else {
      //this.router.navigate(['/reward']);
    }
  }
  async openeemQuiz() {
    this.logado = this.accountService.isAuthenticated();
    if (!this.logado) {
      this.login();
    } else {
      this.router.navigate(['/openeem-quiz']);
    }
  }
  async blog() {
    this.logado = this.accountService.isAuthenticated();
    this.router.navigate(['/blog']);
  }
  async sobre() {
    this.logado = this.accountService.isAuthenticated();
    //this.router.navigate(['/sobre']);
  }
  async bibliotecaCientifica() {
    this.logado = this.accountService.isAuthenticated();
    //this.router.navigate(['/biblioteca-cientifica']);
  }
  private login(): void {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.autoFocus = true;
    dialogConfig.width = '393px';
    dialogConfig.height = '433px';
    const dialogRef = this.dialog.open(LoginComponent, dialogConfig);
    dialogRef.afterClosed().subscribe((retorno) => {
      if (retorno) {
        this.logado = true;
      }
    });
  }
}

Outro componente pagina-inicial-logado.component

import { Component, OnInit } from '@angular/core';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { NgbCarouselConfig } from '@ng-bootstrap/ng-bootstrap';
import { AccountService } from 'src/app/core/auth/account.service';
import { PublicoService } from 'src/app/service/publico.service';
import { CadastrarComponent } from '../modal/cadastrar/cadastrar.component';
import { LoginComponent } from '../modal/login/login.component';
@Component({
  selector: 'app-pagina-inicial-logado',
  templateUrl: './pagina-inicial-logado.component.html',
  styleUrls: ['./pagina-inicial-logado.component.scss'],
})
export class PaginaInicialLogadoComponent implements OnInit {
  biliotecas: any[];
  logado: boolean;
  constructor(
    config: NgbCarouselConfig,
    private publicoService: PublicoService,
    private dialog: MatDialog,
    private accountService: AccountService,
    private router: Router
  ) {
    config.showNavigationIndicators = true;
    config.interval = 10000;
    this.biliotecas = [];
    this.logado = false;
  }
  async ngOnInit(): Promise<void> {
    await this.buscarUltimasTres();
    this.logado = this.accountService.isAuthenticated();
  }
  private async buscarUltimasTres(): Promise<void> {
    this.biliotecas = [];
    await this.publicoService
      .buscarUltimasTresBibliotecas()
      .then((biliotecas) => {
        biliotecas.lista.forEach((element: any) => {
          element.arquivo.url =
            'data:' +
            element.arquivo.contentType +
            ';base64,' +
            element.arquivo.arquivo;
          this.biliotecas.push(element);
        });
      });
  }
  login(): void {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.autoFocus = true;
    dialogConfig.width = '393px';
    dialogConfig.height = '433px';
    const dialogRef = this.dialog.open(LoginComponent, dialogConfig);
    dialogRef.afterClosed().subscribe((retorno) => {
      if (retorno) {
        this.logado = true;
      }
    });
  }
  cadastrar(): void {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.autoFocus = true;
    dialogConfig.width = '600px';
    const dialogRef = this.dialog.open(CadastrarComponent, dialogConfig);
    dialogRef.afterClosed().subscribe((retorno) => {
      if (retorno) {
        this.logado = true;
      }
    });
  }
  blog(id?: string): void {
    if (id === null || id === undefined || id === '') {
      this.router.navigate(['/blog']);
    } else {
      this.router.navigate([`blog/${id}/`]);
    }
  }
}

auth-jwt.service - aonde faz o login e guarda o token

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { LocalStorageService, SessionStorageService } from 'ngx-webstorage';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { CLIENTE, OAUTH, SENHA, TOKEN } from '../api/erp.api';
import { StateStorageService } from './state-storage.service';
@Injectable({ providedIn: 'root' })
export class AuthServerProvider {
  constructor(
    private http: HttpClient,
    private $localStorage: LocalStorageService,
    private $sessionStorage: SessionStorageService,
    private stateStorageService: StateStorageService
  ) {}
  getToken(): string {
    return (
      this.$localStorage.retrieve('authentication_token') ||
      this.$sessionStorage.retrieve('authentication_token') ||
      ''
    );
  }
  login(credentials: any): Observable<void> {
    let logar = '?grant_type=password';
    if (credentials.access_token && credentials.provider) {
      logar =
        logar +
        '&access_token=' +
        credentials.access_token +
        '&provider=' +
        credentials.provider;
    } else {
      logar =
        logar +
        '&username=' +
        credentials.email +
        '&password=' +
        encodeURIComponent(credentials.senha);
    }
    const headers = {
      Authorization: 'Basic ' + btoa(SENHA + ':' + CLIENTE),
    };
    return this.http
      .post<any>(environment.AUTH + OAUTH + TOKEN + logar, {}, { headers })
      .pipe(map((response: any) => this.authenticateSuccess(response, true)));
  }
  logout(): Observable<void> {
    this.stateStorageService.clearUsuarioLogado();
    return new Observable((observer) => {
      this.$localStorage.clear('authentication_token');
      this.$sessionStorage.clear('authentication_token');
      observer.complete();
    });
  }
  private authenticateSuccess(response: any, rememberMe: boolean): void {
    const jwt = response.access_token;
    if (rememberMe) {
      this.$localStorage.store('authentication_token', jwt);
    } else {
      this.$sessionStorage.store('authentication_token', jwt);
    }
  }
}

O que pode ser ?

R

não faço ideia kkkkkkk.


agora entendi então, se dá um reload ele funciona normal, se não der reload o funcionamento nao da certo.

Mostra o código exatamente onde acontece o problema, quando deveria dar certo e não dá

L

Pegue o hábito de usar Observable para conseguir obter uma atualização mais fácil nos seus componentes. Usando observables, vc consegue enviar notificações para os componentes que estão “escutando” determinado observable.

Dê uma lida sobre rxjs/BehaviorSubject: https://backefront.com.br/como-usar-behavior-subject/

G

Para o login funcionou

Para o logout não

private userData = new BehaviorSubject<IUser>(undefined);

    setUser(user: any): void {
        this.userData.next(user);
    }

    getUser(): Observable<any> {
        return this.userData.asObservable();
    }

Nos componentes aonde tenho que tenho que verificar se o usuário esta logado eu fiz assim:

async ngOnInit(): Promise<void> {
    await this.buscarUltimasTres();
    this.logado = false;
    this.usuarioService.getUser().subscribe((usuario) => {
      if (usuario != null) {
        this.logado = true;
      }
    });
  }

no logout fiz assim

logout(): void {
    this.usuarioService.setUser(null);
    this.authServerProvider
      .logout()
      .subscribe(null, null, () => this.accountService.authenticate(null));
    this.router.navigate(['/home']);
  }

O que errei ?

L

Uma pergunta, em que momento vc chama a função authenticate de AccountService?


Tente deixar o código assim:

private isAuthenticatedSubject = new BehaviorSubject<IUser>(false);

setAuthenticated(logado: boolean): void {
  this.isAuthenticatedSubject.next(logado);
}

isLogado(): Observable<boolean> {
  return this.isAuthenticatedSubject.asObservable();
}

E nos componentes, em vez de usar o boolean puro, use o observable retornado pelo isLogado. E veja se funciona. Pelo que me lembro, ao renderizar o componente, o angular entende que é um observable e já resolve ele. E caso o subject mude, o observable já será notificado na proxima vez.

G

Como falei o login funcionou.

Mas o logout não

L

Como está o componente que não respeitou o logout? Ele está usando o observable? São só esses dois componentes my-header.component e pagina-inicial-logado.component que devem reagir ao login e logout?

No lugar que for usar a situação de logado, vc deve usar a observable assim:

this.accountService.isLogado().subscribe(valor => this.logado = valor);
G
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { UsuarioService } from 'src/app/service/usuario.service';
import { AccountService } from '../auth/account.service';
import { AuthServerProvider } from '../auth/auth-jwt.service';
@Injectable({ providedIn: 'root' })
export class LoginService {
  constructor(
    private authServerProvider: AuthServerProvider,
    private accountService: AccountService,
    private router: Router,
    private usuarioService: UsuarioService
  ) {}
  login(credentials: any): Observable<void> {
    return this.authServerProvider.login(credentials);
  }
  logout(): void {
    this.usuarioService.setAuthenticated(false);
    this.authServerProvider
      .logout()
      .subscribe(null, null, () => this.accountService.authenticate(null));
    this.router.navigate(['/home']);
  }
}
L

E os componentes onde devem aparecer/desaparecer elementos, como ele está usando a informação que o usuário está logado ou não?

L
Solucao aceita

Uma das formas de usar o observable no componente poderia ser assim:

@Component({
  selector: 'app-my-header',
  templateUrl: './my-header.component.html',
  styleUrls: ['./my-header.component.scss'],
})
export class MyHeaderComponent implements OnInit {
  // ...

  islogado: Observable<boolean>;
  
  // ...

  async ngOnInit() {
    // recupera o observable
    this.islogado = this.accountService.isAuthenticated();
  }

  // ...
}

E no template do componente:

<div *ngIf="islogado | async">
  Esse conteúdo  vai aparecer se o observable "isLogado" for true
</div>
Criado 18 de novembro de 2021
Ultima resposta 19 de nov. de 2021
Respostas 11
Participantes 3