2
respostas

Falha na Autenticação! (Não Resolvido)

*Os códigos enviarei como pergunta, por conta de limitação de caractéres.

*Nos arquivos, utilizo '// ...' para descrever o que está acontecendo e '// 1, 2, 3...' para ajudar à entender o fluxo.

Vamos usar como base o seguinte login: Username: teste. Password: 123.

Na primeira vez que eu tento me autenticar eu não consigo. Esse subscribe (que está no '// 6') retorna vazio para a variável arrayUser, fazendo com que a validação falhe, pois não retornou nada. Isso teria que acontecer quando eu digito um usuário inválido, mas no caso, eu digitei as credenciais corretas.

Nesse print, mostrar o valor digitado, que está correto, e mostra os dados do usuário retornado, que no caso é undefined, pois é vazio:

Print da primeira tentativa de autenticação

Agora, quando eu tento me autenticar novamente (pela segunda vez), digitando as mesmas credenciais, o subscribe finalmente retorna um objeto para o arrayUser e a minha autenticação funciona perfeitamente. Como pode ver, agora ao invés de undefined, retorna os dados do user:

Print da segunda tentativa de autenticação

*Obs: Meu projeto não tá igual em relação ao do instrutor; Eu estou usando Json-Serve do Typicode ao invés da API do instrutor; Minha versão no npm é: 6.9.0; Minha versão do node.js é: 10.16.3.

2 respostas

Meu signin.component.ts:

import { AuthService } from './../../core/auth.service';
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { User } from 'src/app/user/user';
import { Router } from '@angular/router';

@Component({
  templateUrl: './signin.component.html',
})
export class SigninComponent implements OnInit {
  loginForm: FormGroup;
  user: User;

  // Usarei para dar foco do input do password quando login estiver inválido
  @ViewChild('passwordInput') el:ElementRef;

  constructor(private formBuilder: FormBuilder, private authService: AuthService, private router: Router) {}

  ngOnInit(): void {
    this.loginForm = this.formBuilder.group({
      username: ['', Validators.required],
      password: ['', Validators.required]
    });
  }

  login() {
    // 1
    // Pegar valor do input username
    const username = this.loginForm.get('username').value;

    // 2
    // Pegar valor do input password
    const password = this.loginForm.get('password').value;

    console.log('Authenticate(): \n' + 'Username digitado: ' + username + ', Senha digitada: ' + password);
    // 3
    // A minha função de authenticate retorna um usuário da classe User
    this.user = this.authService.authenticate(username, password);

    // 9
    // Se o usuário for retornado vazio (ou seja, não achado), entrará nessa consição de if
    if (!this.user) {
      // Abre alerta com essa msg
      alert('Invalid username or password');

      // Reseta apenas o input password
      this.loginForm.get('password').reset();

      //Dá foco no input password
      this.el.nativeElement.focus();
    } else {
      // Caso voltar um usuário válido, redirecionar para essa rota
      this.router.navigateByUrl('/photos/user/' + this.user.id);
    }
  }
}

Meu auth.service.ts:

import { User } from 'src/app/user/user';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Injectable, Input } from '@angular/core';

const API_URL = 'http://localhost:3000'

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  user: User;
  arrayUser = [];

  constructor(private http: HttpClient) { }

  getUserByName(username: string): Observable<User[]> {
    // 5
    // Retorna lista de usuário pelo nome porque EU NÃO ESTOU USANDO A API DO INSTRUTOR, e sim o Typicode com Json-server
    return this.http.get<User[]>(API_URL + '/user?username=' + username);
  }

  authenticate(pUsername: string, pPassword: string) {
    // 4
    // Eu chamo a function de buscar o usuário, e retorna uma lista com apenas um registro

    // 6
    // Então eu descarrego os dados na variável arrayUser
    this.getUserByName(pUsername)
    .subscribe(u => this.arrayUser = u);

    console.log('Valor do arrayUser após receber retorno do getUserByName(): ' + this.arrayUser + '\n');

    // 7
    // A variável arrayUser é agora uma lista de 1 objeto de usuário
    // Então eu preciso fazer essa converção para que se torne um objeto
    // Então aqui eu tô convertendo esse array com um objeto para um objeto
    this.user = this.arrayUser.reduce(
      (obj, item) => Object.assign(obj, { id: item.id, username: item.username, password: item.password }), {});

    console.log('Username digitado: ' + pUsername + ', Senha digitada: ' + pPassword + '\nId do user: ' + this.user.id + ', Username do user: ' + this.user.username + ', Senha do user: ' + this.user.password + '\n');

    // 8
    // Valida de a senha do user encontrado for a mesma do campo digitado
    if (this.user.password === pPassword) {
      // Retorna o usuário
      return this.user;
    }
  }
}

Meu signin.component.html:

<h4 class="text-center">Login</h4>

<form [formGroup]="loginForm" class="form mt-4" (submit)="login()">

    <div class="form-group">
        <input
            formControlName="username"
            class="form-control"
            placeholder="user name"
            autofocus>
        <small *ngIf="loginForm.get('username').errors?.required"
          class="text-danger d-block mt-2">
          Username is required!
        </small>
    </div>

    <div class="form-group">
        <input
            #passwordInput
            formControlName="password"
            type="password"
            class="form-control"
            placeholder="password">
        <small *ngIf="loginForm.get('password').errors?.required"
          class="text-danger d-block mt-2">
          Password is required!
        </small>
    </div>

    <button
        [disabled]="loginForm.invalid"
        type="button"
        (click)="login()"
        class="btn btn-primary btn-block">
        login
    </button>

</form>

<p>Not a user?<a>Register now</a></p>

Meu user.ts:

export class User {
  constructor(
    public id: number,
    public username: string,
    public password: string) {}
}

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software