código

11 jun, 2019

Criando uma aplicação (Internet Banking) com Angular 6 — na prática e sem complicações – parte 5

Publicidade

Eaeee pessoal, tudo certo? Comigo está tudo bem! Começo a parte 5 da série muito feliz em ver a repercussão. Saber que posso estar ajudando não tem preço. Peço desculpa pela demora, mas como já sabemos a vida é uma correria e é difícil tirar tempo para fazer as coisas.

Esse post está caprichado explico técnicas profissionais de desenvolvimento, incluindo como debugar o typescript com breakpoints e muito mais.

Sem mais delongas, bora pro conteúdo! a antes de começarmos de fato, caso não tenha acompanhado as primeiras partes da série segue o link abaixo.

Parte 1
Parte 2
Parte 3
Parte 4

O código do projeto você pode baixar e acompanhar pelo Github clicando Aqui

Agora que estamos atualizado(as) vamos que vamos para nossa 5 parte que está muito f##da.

Resultado dessa parte

Onde paramos

Na parte 4 da série finalizamos criando o component home-logada lembra? Caso não lembre segue o gif para refrescar sua memória.

Após isso fiquei devendo a criação e autenticação da aplicação então, vamos lá!

Criando a autenticação da aplicação

Autenticar uma aplicação significa proteger nossas rotas, impedindo assim, que qualquer pessoa acesse o painel do nosso sistema sem credenciais. Você não gostaria que outra pessoa tivesse acesso aos seus dados sensíveis não é mesmo? pois bem, apenas quem possuir as credenciais terá acesso a home logada.

Criando o arquivo de autenticação

Na pasta raiz da aplicação crie um arquivo chamado auth.guard.ts e atualize-o com o código abaixo:

import { AuthService } from './auth.service';
import { Injectable } from '@angular/core';import { CanActivate, Router } from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate {
base_url: string;
constructor(
private authService: AuthService,
private router: Router) { }
canActivate() {
// Verifica se existe Token
if (this.authService.isAuthenticated()) {
// Caso exista token retorna true
return true;
} else {
// Caso não exista envia para página de cpf não é cadastrado
this.router.navigate(['/acesso-negado']);
return false;
}
}
}
Ainda na pasta raiz da aplicação crie também um arquivo chamado auth.service.ts e atualize-o com o código abaixo:
import { Injectable } from '@angular/core';
@Injectable()
export class AuthService {
isAuthenticated() {
// pega o token cadastro
const token = localStorage.getItem('cadastro');
// checa se existe token
if (token) {
return true;
}
return false;
}
}

A estrutura de pastas do projeto ficou assim:

Protegendo as rotas da aplicação

Abra o arquivo app.module.ts e importe os arquivo de autenticação que acabamos de criar:

import { AuthGuard } from ‘auth.guard’; import { AuthService } from ‘auth.service’;

Após isso abra o arquivo app-routing.module.ts e adicione a propriedade canActive para a rota home-logada.

Com isso não é mais possível acessar o component home-logada sem credenciais.

Veja:

Perfeito! nossa autenticação está funcionando.

Como nossa autenticação funciona?

Vamos debugar a aplicação para ver os detalhes.

Na home da aplicação, caso esteja o Google Chrome abra o Dev tools: Ctrl + Shift + I.

Procure pela aba Sources

Após isso, digite Ctrl para procurar pelo arquivo auth.service.ts e clique na linha 7 para adicionar um breakpoint.

Agora vamos tentar acessar a home logada novamente.

Repare que a condição

// checar se existe token
if (token) { // null
  return true;
}

// caiu 
return false;

retorna null, isso quer dizer que não temos o token (nosso cadastro) no localStorage, logo, o retorno é falso e não conseguimos acessar a rota home-logada.

Vamos realizar o cadastro e depois vamos debugar novamente.

Vamos tentar acessar a home-logada novamente e debugar novamente e ver o resultado

Vitoria!!!

Percebeu que o o token aqui é o objeto com o cadastro do usuário? Pois bem a condição agora retorna true e, a a partir de agora, podemos acessar a home-logada.

Criando Component de Login

Acima fizemos apenas um teste ao digitar diretamente a rota “home-logada”. Nenhum usuário irá realizar login desta forma. Precisamos criar um component de login para isso.

Observação: caso o usuário já possua cpf cadastrado ele pode usar o campo “ Acesse sua conta” no header da aplicaçao.

Mas, pensando em usabilidade, vamos criar um component de login também.

Siga os passos abaixo:

  1. Crie o Component login;

2. Abra o arquivo cadastro-concluido.component.ts

3. Atualize-os da seguinte maneira

Arquivo: cadastro-concluido.component.html

<div class=”wrapper-content”>
<h1>Cadastro concluído com sucesso!</h1>
<p>Ficamos felizes em tê-lo como nosso cliente. Em 10 segundos você será redirecionado para a página de Login, utilize seu CPF
para realizar acessar o seu painel.</p>
<button (click)=’navegarParaLogin()’>Não quero esperar leve-me para página de Login</button>
</div>
Arquivo: cadastro-concluido.component.ts
import { Component, OnInit } from ‘@angular/core’;
import { Router } from ‘@angular/router’;
@Component({
selector: ‘app-cadastro-concluido’,
templateUrl: ‘./cadastro-concluido.component.html’,
styleUrls: [‘./cadastro-concluido.component.css’]
})
export class CadastroConcluidoComponent implements OnInit {
constructor(private router: Router) { }
ngOnInit() {
this.navegarParaLogin();
}
navegarParaLogin() {
setTimeout(() => {
this.router.navigate([‘/login’]);
}, 10000);
}
}
Arquivo: cadastro-concluido.component.css
.wrapper-content {
width: 100vw;
height: 70vh;
z-index: -9999;
top: -60px;
}
.wrapper-content
h1,
p {
text-align: center;
margin-top: 100px;
}
.wrapper-content button {
display: block;
margin: 0 auto;
padding: 20px;
font-size: 24px;
}
.wrapper-content p {
font-size: 18px;
}
Abra o arquivo login.componet.html e atualize com o código abaixo:
<form [formGroup]="formLogin">
<div class="form-row align-items-center">
<div class="col-auto my-1">
<div class="form-check">
<label class="form-check-label">
<b>Acesse</b> sua conta
</label>
<input
type="text"
class="form-control"
formControlName="cpf"
placeholder="Digite seu CPF"
(keypress)="onlynumber($event)"
maxlength=11>
</div>
</div>
<div class="col-auto my-1">
<button type="submit" class="btn btn-primary acessar-conta" (click)="login()">Acessar</button>
</div>
</div>
</form>
Abra o arquivo login.componet.ts e atualize com o código abaixo:
import { Component, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
formLogin;
theEvent;
key;
regex;
keys;
getCadastro;
message;
constructor(
private fb: FormBuilder,
private router: Router) { }
ngOnInit() {
this.formLogin = this.fb.group({
cpf: ['']
});
}
onlynumber(evt) {
this.theEvent = evt || window.event;
this.key = this.theEvent.keyCode || this.theEvent.which;
this.key = String.fromCharCode(this.key);
this.regex = /^[0-9.]+$/;
if (!this.regex.test(this.key)) {
this.theEvent.returnValue = false;
if (this.theEvent.preventDefault) {
this.theEvent.preventDefault();
}
}
}
login() {
this.getCadastro = JSON.parse(localStorage.getItem('cadastro'));
const cpfPersistido = this.getCadastro['cpf'];
const cpfDigitado = this.formLogin.get('cpf').value;
if (cpfPersistido === cpfDigitado) {
this.router.navigate(['home-logada']);
} else {
this.openDialog();
}
openDialog() {
const dialogRef = this.dialog.open(ModalNotCadastroComponent, {
height: '350px'
});
dialogRef.afterClosed().subscribe(result => {
console.log(`Dialog result: ${result}`);
});
}
}
Abra o arquivo login.componet.css e atualize com o código abaixo:
import { Component, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
formLogin;
theEvent;
key;
regex;
keys;
getCadastro;
message;
constructor(
private fb: FormBuilder,
private router: Router) { }
ngOnInit() {
this.formLogin = this.fb.group({
cpf: ['']
});
}
onlynumber(evt) {
this.theEvent = evt || window.event;
this.key = this.theEvent.keyCode || this.theEvent.which;
this.key = String.fromCharCode(this.key);
this.regex = /^[0-9.]+$/;
if (!this.regex.test(this.key)) {
this.theEvent.returnValue = false;
if (this.theEvent.preventDefault) {
this.theEvent.preventDefault();
}
}
}
login() {
this.getCadastro = JSON.parse(localStorage.getItem('cadastro'));
const cpfPersistido = this.getCadastro['cpf'];
const cpfDigitado = this.formLogin.get('cpf').value;
if (cpfPersistido === cpfDigitado) {
this.router.navigate(['home-logada']);
} else {
this.openDialog();
}
openDialog() {
const dialogRef = this.dialog.open(ModalNotCadastroComponent, {
height: '350px'
});
dialogRef.afterClosed().subscribe(result => {
console.log(`Dialog result: ${result}`);
});
}
}
Agora precisamos atualizar o arquivo app-routing.module.ts com a nova rota ‘login’.

Arquivo: app-routing.module.ts

As rotas atualizadas ficaram assim:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { ContentComponent } from './../content/content.component';
import { CadastroClientesComponent } from './../cadastro-clientes/cadastro-clientes.component';
import { CadastroConcluidoComponent } from '../cadastro-concluido/cadastro-concluido.component';
import { HomeLogadaComponent } from '../home-logada/home-logada.component';
import { AuthGuard } from 'auth.guard';
import { AcessoNegadoComponent } from '../acesso-negado/acesso-negado.component';
import { LoginComponent } from '../login/login.component';
const routes: Routes = [
{ path: '', component: ContentComponent },
{ path: 'cadastro-clientes', component: CadastroClientesComponent },
{ path: 'cadastro-concluido', component: CadastroConcluidoComponent },
{ path: 'home-logada', component: HomeLogadaComponent, canActivate: [AuthGuard] },
{ path: 'acesso-negado', component: AcessoNegadoComponent},
{ path: 'login', component: LoginComponent},
];
@NgModule({
imports: [
CommonModule,
RouterModule.forRoot(routes)
],
declarations: [],
exports: [RouterModule]
})
export class AppRoutingModule { }

Componentizando o Login

Aqui vamos componentizar melhor nossa aplicação

Abra o arquivo header.component.html e remova o formulário com o campo de cpf.

Segue Nossa arquivo header.component.html atualizado

<div class=”wrapper-header”>
<div class=”row”>
<div class=”col-xs-12 col-md-8">
<ul class=”menu-header”>
<li>Abra sua conta</li>
<li>Investimentos</li>
<li>Planos</li>
</ul>
</div>
<div class=”col-xs-12 col-md-4">
<div class=”position-login”>
<app-login></app-login>
</div>
</div>
</div>
</div>

Ficamos sem nosso campo de cpf veja:

Utilizando o component Login

Agora insira a tag <app-login></app-login>, do component login na parte que você recortou.

Viu só? estamos utilizando o Component login em dois lugares diferentes.

Vamos realizar o fluxo completo agora

Resumo final

Para o post não ficar muito grande, vamos ficando por aqui. Nas próximas aulas vamos melhorar o header da aplicação e fazer o logout e criar os cards com a lógica do nosso Internet Banking.

Eae curtiu o post de hoje? está com dúvidas não deixe nos comentários.

Se jogar conversa fora segue meu Twitter; @danilodev_silva

Abraço!