Files
soft_usite/rest/controllers/register_controller.go
T
2026-05-18 23:50:50 -05:00

280 lines
7.9 KiB
Go
Executable File

package controllers
import (
"crypto/rand"
"errors"
"fmt"
"log"
"math/big"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/sujit-baniya/fiber-boilerplate/app"
"github.com/sujit-baniya/fiber-boilerplate/config"
"github.com/sujit-baniya/fiber-boilerplate/pkg/auth"
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
// Función para renderizar la página de registro
func RegisterGet(c *fiber.Ctx) error {
data := getFlashData(c)
data["title"] = "Register | "
if err := c.Render("auth/register", data, "layouts/landing"); err != nil { //nolint:wsl
panic(err.Error())
}
return nil
}
// Función para manejar la solicitud de registro
func RegisterPost(c *fiber.Ctx) error {
register := c.Locals("register").(models.RegisterForm)
user, err := register.Signup()
if err != nil {
return app.Http.Flash.WithError(c, fiber.Map{
"error": true,
"message": "Error on register request: " + err.Error(),
}).Redirect("/register")
}
store := app.Http.Session.Get(c) // obtener/crear nueva sesión
store.Set("user_id", user.ID) // guardar en el almacenamiento
_ = store.Save()
go services.SendConfirmationEmail(user.Email, services.GetPublicURL(), user.NombreUsuario)
return c.Redirect("/")
}
// Función para verificar el correo electrónico registrado
func VerifyRegisteredEmail(c *fiber.Ctx) error {
return c.Redirect("/app")
}
// Función para reenviar el correo de confirmación
func ResendConfirmEmail(c *fiber.Ctx) error {
user, _ := auth.User(c)
go services.SendConfirmationEmail(user.Email, services.GetPublicURL(), user.NombreUsuario)
return c.Redirect("/")
}
func ReenvioEmail(c *fiber.Ctx) error {
usuarioID := c.Params("id") // Usa Params para obtener el parámetro de la ruta
user, err := models.GetUserById(usuarioID)
if err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"success": false,
"message": "Usuario no encontrado: " + err.Error(),
})
}
// Reenvío del correo electrónico de forma asíncrona
go services.SendConfirmationEmail(user.Email, services.GetPublicURL(), user.NombreUsuario)
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"success": true,
"message": "Email reenviado correctamente",
})
}
// Función para manejar la solicitud de restablecimiento de contraseña
func RequestPasswordResetPost(c *fiber.Ctx) error {
usuario := c.FormValue("nombre_usuario")
fmt.Println("Usuario recibido:", usuario)
user, err := models.GetUserByUsuario(usuario)
if err != nil || user == nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "Usuario inactivo o no existente",
})
}
usuario_email := user.Email
log.Println("Sending password reset email to:", usuario_email)
go services.SendPasswordResetEmail(usuario_email, services.GetPublicURL())
return c.JSON(fiber.Map{
"success": true,
"message": "We've sent an email to reset your password to your registered email address",
})
}
// todo: Generar contrasenas aleatorias /do/generate-password
func generatePassword(length int) (string, error) {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&"
var password strings.Builder
for i := 0; i < length; i++ {
randomIndex, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
if err != nil {
return "", err
}
password.WriteByte(charset[randomIndex.Int64()])
}
return password.String(), nil
}
func hashPassword(password string) (string, error) {
hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hashed), nil
}
func updatePassword(nombreUsuario, plainPassword string) error {
var user models.RegisterForm
result := app.Http.Database.DB.Where("nombre_usuario = ?", nombreUsuario).First(&user)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return errors.New("codigo no pertenece a ningun usuario")
}
if user.Password != "" {
return errors.New("este usuario ya cuenta con una contraseña")
}
hashedPassword, err := hashPassword(plainPassword)
if err != nil {
return err
}
user.Password = hashedPassword
if err := app.Http.Database.DB.Save(&user).Error; err != nil {
return err
}
return nil
}
func GeneratePasswordPost(c *fiber.Ctx) error {
// Parsear el cuerpo de la solicitud
var body struct {
NombreUsuario string `json:"nombre_usuario"`
}
if err := c.BodyParser(&body); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "Error al analizar el cuerpo de la solicitud",
})
}
if body.NombreUsuario == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "El codigo de usuario es requerido",
})
}
// Generar la contraseña
password, err := generatePassword(12)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"success": false,
"message": "Error generando contraseña",
})
}
// Actualizar la contraseña en la base de datos
if err := updatePassword(body.NombreUsuario, password); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"success": false,
"message": err.Error(),
})
}
// Responder con la contraseña generada
return c.JSON(fiber.Map{
"success": true,
"message": "Contrasena generada exitosamente",
"password": password,
})
}
// Función para renderizar la página de restablecimiento de contraseña
func PasswordReset(c *fiber.Ctx) error {
token := c.Query("t")
if err := c.Render("auth/password-reset", fiber.Map{
"Title": "Password Reset",
"Token": token,
}, "layouts/landing"); err != nil {
panic(err.Error())
}
return nil
}
func PasswordResetPost(c *fiber.Ctx) error {
// Recuperar el nombre de usuario y la nueva contraseña del formulario
nombreUsuario := c.FormValue("nombre_usuario")
password := c.FormValue("password")
// Validar que ambos campos estén presentes
if nombreUsuario == "" || password == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Los campos nombre_usuario y password son obligatorios.",
"error": true,
})
}
// Imprimir los datos recibidos (opcional para depuración)
fmt.Printf("Datos recibidos: nombre_usuario=%s, password=%s\n", nombreUsuario, password)
// Buscar al usuario en la base de datos por nombre de usuario
user, err := models.GetUserByUsuario(nombreUsuario)
if err != nil || user == nil {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "Usuario no encontrado.",
"error": true,
})
}
hash := config.Hash{}
// Encripta la nueva contraseña
hashedPassword, err := hash.Create(password)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error al encriptar la contraseña",
"error": true,
})
}
// Asigna la contraseña encriptada al modelo
password = hashedPassword
// Actualizar la contraseña del usuario
err = models.UpdateUserPassword(user.ID, password)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error al actualizar la contraseña.",
"error": true,
})
}
// Redirigir al usuario al formulario de inicio de sesión después del éxito
return c.Redirect("/login")
}
// Función para renderizar la página de solicitud de restablecimiento de contraseña
func RequestPasswordReset(c *fiber.Ctx) error {
data := getFlashData(c)
data["title"] = "Password Reset | "
if err := c.Render("auth/request-password-reset", data, "layouts/landing"); err != nil { //nolint:wsl
panic(err.Error())
}
return nil
}
func TokenVencido(c *fiber.Ctx) error {
// Renderiza la vista con el layout layouts/main
if err := c.Render("token_vencido", nil, "layouts/landing"); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error rendering template",
"error": err.Error(),
})
}
return nil
}