Aula 26 - Implementação da Funcionalidade Esqueceu a Senha

Links da Aula:

Código da Aula MailHog

Introdução

Nesta aula, iremos implementar a funcionalidade de recuperação de senha para esse aplicativo que estamos construindo com React no frontend e Golang com o framework Fiber no backend. Abordaremos a adição de rotas, criação de componentes React e a integração com o MailHog para simulação de envio de emails. 1. Frontend: Modificação no Componente de Login e Adição de Link para Recuperação de Senha No arquivo Login.tsx, iremos realizar as seguintes adições:
  • Link de Recuperação: Iremos inserir um link "Forgot Password?" que redireciona o usuário para a página de recuperação. Este link será implementado usando o componente Link do react-router-dom, garantindo uma navegação fluida entre as páginas sem recarregar a página.
  • Formulário de Login: O formulário já existente para captar o email e a senha do usuário será adaptado para incluir o novo link de recuperação. Ao submeter o formulário, uma requisição POST será enviada ao servidor utilizando a biblioteca Axios. O endpoint da API será definido por uma variável de ambiente para flexibilidade e segurança.

src/pages/Login.tsx


import React, { useState, SyntheticEvent } from 'react';
import axios from 'axios';
import { Navigate, Link } from 'react-router-dom';

const Login: React.FC<{ setLogin: (loggedIn: boolean) => void }> = ({ setLogin }) => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [redirect, setRedirect] = useState(false);
  const submit = async (e: SyntheticEvent) => {
    e.preventDefault();

    // Using environment variable for API URL
    const apiURL = process.env.REACT_APP_API_URL || 'http://localhost:3000'; // Fallback to localhost if environment variable is not set

    try {
        // Fix axios.post call with URL and data as separate arguments
        const response = await axios.post(`${apiURL}/api/login`, {
          email, // Simplification, since the name of the property and variable are the same
          password,
        });

        // Check the response here (example: whether login was successful based on the response status)
        if (response.status === 200) {
          // If the response is successful, set the state to redirect
          setLogin(true);
          setRedirect(true);
        } else {
          // Here you can handle other status codes or set a state to display an error message
          console.error("Login falhou com status:", response.status);
          // Ideally I would set an error state here to inform the user that login failed
        }
      } catch (error) {
      console.error("Erro ao fazer login:", error);
      // Here you could also set an error state to inform the user about the problem
    }
  };

  if(redirect){
    return <Navigate to="/"/>;
  }
  return (
    <form className='form-floating' onSubmit={submit}>
      <h1 className="h3 mb-3 fw-normal">Please sign in</h1>
      <div className="form-signin">
        <input type="email" className="form-control" placeholder="name@example.com" required 
          onChange={e => setEmail(e.target.value)}
        />
      </div>
      <div className="form-signin">
        <input type="password" className="form-control" placeholder="Password" required 
          onChange={e => setPassword(e.target.value)}
        />
        <div className="mb-3">
          <Link to="/forgot">Forgot Password?</Link>
        </div>
      </div>
      <button className="form-signin btn btn-primary w-100 py-2" type="submit">Sign in</button>
      <p className="mt-5 mb-3 text-body-secondary">&copy; 2017–2024</p>
    </form>
  );
}
export default Login;
2. Frontend: Criação do Componente Forgot.tsx Este componente será responsável pela página onde o usuário pode solicitar a redefinição de senha:
  • Formulário de Recuperação: Um campo de entrada para o email será fornecido, juntamente com um botão para enviar o pedido. Ao submeter, o email será enviado ao backend via uma requisição POST usando Axios.
  • Feedback ao Usuário: Respostas de sucesso ou erro serão exibidas usando um estado que controla uma mensagem de alerta, informando se o email foi enviado ou se ocorreu algum erro.

src/pages/Forgot.tsx


import React, { useState, SyntheticEvent } from 'react';
import axios from 'axios';

const Forgot = () => {
  const [email, setEmail] = useState('');
  const [notify, setNotify] = useState({
    show: false,
    error: false,
    message: ''
  });

  const submit = async (e: SyntheticEvent) => {
    e.preventDefault();
    try {
      await axios.post('forgot', {
        email
      });
      setNotify({
        show: true,
        error: false,
        message: 'Email was sent!'
      });
    } catch (e) {
      setNotify({
        show: true,
        error: true,
        message: 'Email does not exist!'
      });
    }
  };

  let info;
  if (notify.show) {
    info = (
      <div className={notify.error ? 'alert alert-danger' : 'alert alert-success'} role="alert">
        {notify.message}
      </div>
    );
  }

  return (
    <form className="form-floating" onSubmit={submit}>
      {info}
      <h1 className="h3 mb-3 font-weight-normal">Please set your email</h1>
      <div className="form-signin">
        <input
          type="email"
          className="form-control mb-3"
          placeholder="name@example.com"
          required
          onChange={e => setEmail(e.target.value)}
        />
      </div>
      <button className="form-signin btn btn-primary w-100 py-2" type="submit">
        Send Email
      </button>
      <p className="mt-5 mb-3 text-body-secondary">© 2017–2024</p>
    </form>
  );
};

export default Forgot;
3. Configuração de Rotas no App.tsx Para integrar a nova página de recuperação de senha ao fluxo de navegação do aplicativo, é necessário adicionar uma rota específica para este componente no arquivo de rotas principal, o App.tsx. Usamos o BrowserRouter e Routes do react-router-dom para definir essas rotas.

src/App.tsx 


import React, { useState, useEffect } from "react";
import axios from "axios";
import "./App.css";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Login from "./pages/Login";
import Home from "./pages/Home";
import Register from "./pages/Register";
import Forgot from "./pages/Forgot";
import Nav from "./components/Nav";

function App() {
  const [user, setUser] = useState(null); // State to store user data
  const [login, setLogin] = useState(false);

  useEffect(() => {
    (async () => {
      try {
        const response = await axios.get("user");
        const user = response.data;
        setUser(user);// Update the state with user data
      } catch (e) {
        console.error("Error loading user data", e);
        setUser(null); // Sets the user to null in case of error
      }
    })();
  }, [login]);

  return (
    <div className="App">
      <Router>
        <Nav user={user} setLogin={ () => setLogin(false) }/>
        <Routes>
          <Route path="/" element={<Home user={user} />} />
          <Route path="/login" element={<Login setLogin={() => setLogin(true)} />} />
          <Route path="/register" element={<Register />} />
          <Route path="/forgot" element={<Forgot/>} />
        </Routes>
      </Router>
    </div>
  );
}

export default App;

Testando a Feature "Forgot" com MailHog

Para garantir que a feature "Forgot" funcione corretamente, iremos utilizar o MailHog para emular um serviço de e-mail durante nossos testes. O MailHog é uma ferramenta simples e eficiente para capturar e visualizar e-mails enviados pelo nosso aplicativo durante o desenvolvimento.

Passos para Configurar o MailHog

  1. Se ainda não tem o MailHog, faça o download e Instale no seu sistema:
    • Baixe o MailHog a partir do repositório oficial: MailHog Releases
    • Siga as instruções de instalação específicas para o seu sistema operacional.
  2. Execute o MailHog:
    • Após a instalação, execute o MailHog. Ele começará a escutar por e-mails enviados em localhost:1025 e fornecerá uma interface web em localhost:8025.
  3. Acesse a Interface Web do MailHog:
    • Para visualizar os e-mails capturados, abra um navegador e navegue até localhost:8025. Observe que a URL 0.0.0.0:8025 não funcionará, pelo menos na versão para o Windows, então é necessário usar localhost:8025.

Testando a Feature "Forgot"

Com o MailHog em execução:
  1. Navegue até a página de Forgot.
  2. Insira um endereço de e-mail válido e envie o formulário.
  3. Abra a interface do MailHog em localhost:8025 no seu navegador.
  4. Verifique se o e-mail de recuperação foi recebido corretamente.
Usando o MailHog, podemos testar a funcionalidade de envio de e-mails sem a necessidade de um servidor de e-mails real, garantindo que nossas implementações estejam corretas antes de mover para um ambiente de produção.

Conclusão

Parabéns por concluir a aula de hoje sobre a implementação da funcionalidade "Forgot Password"! Ao longo desta aula, aprendemos como capturar e-mails de usuários que desejam redefinir suas senhas e enviar instruções de recuperação utilizando o MailHog para emular um serviço de e-mail. Isso nos permitiu testar de forma eficiente sem a necessidade de um servidor de e-mails real.

O que foi abordado:

  • Implementação do formulário de recuperação de senha.
  • Configuração e uso do MailHog para testes de e-mail.
  • Teste da funcionalidade "Forgot Password" para garantir que os e-mails sejam enviados corretamente.
A próxima aula será a última deste tutorial, iremos abordar a funcionalidade "Reset Password".

Nos vemos lá então, na última aula deste tutorial!

Valeu, ;) \o/