Aula 16 - Golang - Fiber - Implementando a Redefinição de Senhas

Nesta aula de Fiber, abordaremos a funcionalidade de redefinição de senhas. A seguir, estão os principais tópicos da aula:
  • Criação do Controlador de Redefinição de Senha (Forgot Controller): Criaremos um novo controlador chamado "Forgot Controller" para tratar a lógica de redefinição de senhas.
  • Adição de um novo Modelo: Antes de adicionar a lógica de redefinição, vamos criar um novo modelo chamado "Password Reset" para armazenar os dados necessários no banco de dados.
  • Criação da Tabela de Redefinição de Senha (password_reset): A tabela "password_reset" será criada através de uma migração para armazenar as informações relacionadas à redefinição de senhas.
  • Implementação da Função "Forgot" no Controlador: Dentro do "Forgot Controller", vamos implementar a função "forgot" para lidar com a lógica de geração do token de redefinição de senha e salvar os dados no banco de dados.
  • Geração de Tokens Aleatórios: Teremos uma função para gerar um token aleatório de 12 caracteres para cada solicitação de redefinição de senha.
  • Armazenamento do Token no Banco de Dados: O token gerado será armazenado junto com o endereço de e-mail do usuário no banco de dados na tabela password_reset.
  • Teste da Funcionalidade de Redefinição de Senha: A funcionalidade de redefinição de senha será testada usando um cliente HTTP (No meu caso, o Postman), para verificar se o registro foi inserido corretamente no banco de dados.
  • Próximos Passos: No próximo tutorial, será abordado o envio de e-mails contendo os tokens de redefinição de senha para os usuários.

Mãos a Obra

Vamos criar um novo controle, para isso, crie o arquivo: fiber-project/controllers/forgotController.go E um novo modelo: fiber-project/models/passwordReset.go 

Controle forgotController

fiber-project/controllers/forgotController.go

package controllers

import (
        "github.com/gofiber/fiber/v2"
        "fiber-project/database"
	"fiber-project/models"
        "math/rand"
)

func Forgot(c *fiber.Ctx) error {
    var data map[string]string

    if err := c.BodyParser(&data); err != nil {
        return err
    }

    token := RandStringRunes(12)
    passwordReset := models.PasswordReset{
        Email: data["email"],
        Token: token,
    }

    database.DB.Create(&passwordReset)
    
    return c.JSON(fiber.Map{
        "message": "success",
    })
}

func RandStringRunes(n int) string {
    var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

    b := make([]rune, n)
    for i := range b {
        b[i] = letterRunes[rand.Intn(len(letterRunes))]
    }
    return string(b)
}

Fugindo ao escopo da aula, uma explicação rápida sobre Runa em Go

Em Golang, o termo "runa" refere-se a um tipo de dado que representa um único ponto de código Unicode (caractere) na linguagem. Em outras palavras, uma runa é um valor numérico que corresponde a um único caractere em UTF-8, que é o formato de codificação de caracteres usado por padrão em Go.

Exemplo Rápido (Runa)


package main

import "fmt"

func main() {
    var myRune rune
    // 'A' representa a runa do caractere 'A' em Unicode
    myRune = 'A'
    // Saída: Valor UTF-8 da runa 'A': U+0041
    fmt.Printf("Valor UTF-8 da runa %c: %U\n", myRune, myRune)
}

Função RandStringRunes()

A função RandStringRunes() recebe um parâmetro n, que determina o tamanho da string aleatória que será gerada. Ela retorna uma string contendo caracteres aleatórios gerados a partir de uma lista de caracteres permitidos. var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
  • Cria um slice de rune chamado letterRunes, que contém todos os caracteres permitidos para a string aleatória. Neste caso, são as letras maiúsculas e minúsculas do alfabeto.
b := make([]rune, n)
  • Cria um novo slice de rune chamado b, com o tamanho n. Esse slice será usado para armazenar os caracteres aleatórios gerados.
for i := range b { ... }
  • Inicia um loop for para percorrer o slice b.
  • O loop vai de 0 até n-1.
b[i] = letterRunes[rand.Intn(len(letterRunes))]
  • A cada iteração do loop, um valor aleatório é escolhido a partir do slice letterRunes utilizando a função rand.Intn.
  • rand.Intn(len(letterRunes)) retorna um número inteiro aleatório entre 0 e o comprimento de letterRunes - 1. Esse número é usado como índice para selecionar um caractere aleatório do slice letterRunes.
return string(b)
  • Após o loop, a função retorna a string resultante, que é obtida ao converter o slice de rune b para uma string.
Em resumo, a função RandStringRunes gera uma string aleatória de tamanho n, contendo caracteres do alfabeto maiúsculo e minúsculo, escolhidos aleatoriamente. Ela é útil quando você precisa gerar strings aleatórias para fins como senhas, tokens, ou qualquer outro uso que requeira dados aleatórios.

Voltando ao projeto

Modelo passwordReset

fiber-project/models/passwordReset.go 

package models

type PasswordReset struct {
    Id uint
    Email string
    Token string
}

Vamos adicionar ao connection.AutoMigrate esse novo model

fiber-project/database/connect.go


package database

import (
	"fiber-project/models"
	"fmt"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func Connect() {
	var dsn = "toticavalcanti:mysql1234@/fluent_admin?charset=utf8mb4&parseTime=True&loc=Local"
	var v = "Não conseguiu conectar ao banco de dados"
	connection, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

	if err != nil {
		panic(v)
	}

	DB = connection

	connection.AutoMigrate(&models.User{}, &models.PasswordReset{})
	fmt.Println("Conexão OK!")
}
Reinicie o servidor, veja que agora temos outra tabela no banco, a password_reset. Agora vamos criar a rota do controle Forgot.

fiber-project/routes/routes.go 


package routes

import (
	"fiber-project/controllers"

	"github.com/gofiber/fiber/v2"
)

func Setup(app *fiber.App) {
	app.Post("/api/register", controllers.Register)
	app.Post("/api/login", controllers.Login)
	app.Get("/api/user", controllers.User)
	app.Post("/api/logout", controllers.Logout)
        app.Post("/api/forgot", controllers.Forgot)
}
Agora vamos acessar http://localhost:3000/api/forgot pelo Postman e fazer uma requisição Post. No body, escolha a aba JSON se tiver usando o Postman, e coloque no body passe o email:

{
    "email": "a@mail.com"
}
Veja que ele gerou e armazenou o token na tabela password_reset além do email.

Código da aula: Github

Redes Sociais:

facebook        

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

É isso!

A gente se vê na próxima. ;)

Até lá!

\o/

Bons estudos. ;)