Files
soft_usite/rest/controllers/users_controller.go
T

576 lines
16 KiB
Go
Executable File

package controllers
import (
"fmt"
"math"
"strconv"
"github.com/gofiber/fiber/v2" //nolint:goimports
"github.com/sujit-baniya/fiber-boilerplate/app"
"github.com/sujit-baniya/fiber-boilerplate/config"
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
)
// RENDER
func Users(c *fiber.Ctx) error {
data := fiber.Map{
"user": c.Locals("user").(map[string]interface{}),
"modules": c.Locals("userModules"),
}
// Renderiza la vista "modules" con el layout "layouts/landing"
if err := c.Render("users", data, "layouts/main"); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error rendering template",
"error": err.Error(),
})
}
return nil
}
// RENDER usuarios gas
func UsersGas(c *fiber.Ctx) error {
data := fiber.Map{
"user": c.Locals("user").(map[string]interface{}),
"modules": c.Locals("userModules"),
}
// Renderiza la vista "modules" con el layout "layouts/landing"
if err := c.Render("users_gas", data, "layouts/main"); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error rendering template",
"error": err.Error(),
})
}
return nil
}
// CONSULTAR TODOS LOS REGISTROS
func GetUsers(c *fiber.Ctx) error {
// Obtener parámetros de consulta para la paginación
pageStr := c.Query("page", "1") // Por defecto, la página es 1
page, err := strconv.Atoi(pageStr)
if err != nil || page < 1 {
page = 1
}
searchQuery := c.Query("search", "") // Obtener el término de búsqueda
limit := 10 // Número de módulos por página
offset := (page - 1) * limit
// Llama a AllUsers con el término de búsqueda
Users, totalUsers, err := models.AllUsersSistema(limit, offset, searchQuery)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error retrieving users",
"error": err.Error(),
})
}
// Llama a AllRoles sin el término de búsqueda para obtener todos los roles
roles, err := models.AllRolesSelect() // Pasamos 0 para limit y offset para obtener todos los roles
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error retrieving roles",
"error": err.Error(),
})
}
// Calcular el total de páginas para usuarios
totalPages := int(math.Ceil(float64(totalUsers) / float64(limit)))
// Envía los usuarios y roles como respuesta JSON junto con la información de paginación
return c.JSON(fiber.Map{
"Users": Users,
"Roles": roles,
"total": totalUsers, // Total de usuarios disponibles
"totalPages": totalPages, // Total de páginas
"page": page, // Página actual
"limit": limit, // Límites por página
})
}
// CONSULTAR TODOS LOS REGISTROS GAS
func GetusersGas(c *fiber.Ctx) error {
// Obtener parámetros de consulta para la paginación
pageStr := c.Query("page", "1") // Por defecto, la página es 1
page, err := strconv.Atoi(pageStr)
if err != nil || page < 1 {
page = 1
}
searchQuery := c.Query("search", "") // Obtener el término de búsqueda
limit := 10 // Número de módulos por página
offset := (page - 1) * limit
// Llama a AllUsers con el término de búsqueda
Users, totalUsers, err := models.AllUsersGas(limit, offset, searchQuery)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error retrieving users",
"error": err.Error(),
})
}
// Calcular el total de páginas para usuarios
totalPages := int(math.Ceil(float64(totalUsers) / float64(limit)))
// Envía los usuarios y roles como respuesta JSON junto con la información de paginación
return c.JSON(fiber.Map{
"Users": Users,
"total": totalUsers, // Total de usuarios disponibles
"totalPages": totalPages, // Total de páginas
"page": page, // Página actual
"limit": limit, // Límites por página
})
}
// GetUser consulta un solo registro de usuario por su ID
func GetUser(c *fiber.Ctx) error {
// Obtiene el ID del parámetro de la URL
idParam := c.Params("id")
fmt.Print(idParam)
// Convierte el parámetro a un uint
userID, err := strconv.ParseUint(idParam, 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid user ID",
"error": err.Error(),
})
}
// Canal para recibir el resultado de la consulta
resultChan := make(chan *models.Users)
errorChan := make(chan error)
// Ejecuta la consulta en una goroutine
go func() {
user, err := models.FindUserByID(uint(userID))
if err != nil {
errorChan <- err
return
}
// Si no hay error, envía el resultado al canal
resultChan <- user
}()
// Espera el resultado o el error de la goroutine
select {
case user := <-resultChan:
// Si el usuario no existe
if user == nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"message": "User not found",
})
}
// Envía el usuario como respuesta JSON
return c.JSON(fiber.Map{
"user": user,
})
case err := <-errorChan:
// Maneja el error
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error retrieving user",
"error": err.Error(),
})
}
}
func UpdateUser(c *fiber.Ctx) error {
var m models.Users
uid, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "ID inválido",
"error": true,
})
}
// Analiza el cuerpo de la solicitud
if err := c.BodyParser(&m); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Error al analizar el cuerpo de la solicitud",
"error": true,
})
}
m.ID = uint(uid)
// Si el campo Estado está presente, solo se actualiza ese campo
if m.Estado != nil {
// Actualiza el estado del usuario
if err := models.UpdateUserEstado(m.ID, *m.Estado); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err.Error(),
"error": true,
})
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "Estado del usuario actualizado con éxito",
"error": false,
"user": m,
})
}
// Verifica que al menos dos de los campos relevantes estén llenos (Name, NombreUsuario, Email)
if (m.Name == "" && m.NombreUsuario == "" && m.Email == "") ||
(m.Name == "" && m.Email == "") ||
(m.NombreUsuario == "" && m.Email == "") {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Se deben llenar al menos dos de los siguientes campos: Name, NombreUsuario, Email",
"error": true,
})
}
// Crea un mapa para los campos que se actualizarán
updates := make(map[string]interface{})
// Agrega los campos que están presentes en la solicitud
if m.Name != "" {
updates["Name"] = m.Name
}
if m.NombreUsuario != "" {
updates["NombreUsuario"] = m.NombreUsuario
}
if m.Email != "" {
updates["email"] = m.Email
}
if m.RoleID != 0 {
updates["role_id"] = m.RoleID
}
updates["telegram_chat_id"] = m.TelegramChatID
// Realiza la actualización de los campos seleccionados
if err := models.UpdateUser(m.ID, m.Name, m.NombreUsuario, m.Email, int(m.RoleID), m.TelegramChatID); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err.Error(),
"error": true,
})
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "Usuario actualizado con éxito",
"error": false,
"user": m,
})
}
func UpdateUserGas(c *fiber.Ctx) error {
var m models.Users
uid, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "ID inválido",
"error": true,
})
}
var existing models.Users
if err := app.Http.Database.DB.First(&existing, uid).Error; err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"message": "Registro no encontrado",
"error": true,
})
}
if err := c.BodyParser(&m); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Error al analizar el cuerpo de la solicitud",
"error": true,
})
}
if m.Name != "" {
existing.Name = m.Name
}
if m.NombreUsuario != "" {
existing.NombreUsuario = m.NombreUsuario
}
if m.NumeroMedidor != "" {
existing.NumeroMedidor = m.NumeroMedidor
}
if m.Email != "" {
existing.Email = m.Email
}
if m.Celular != "" {
existing.Celular = m.Celular
}
if err := app.Http.Database.DB.Save(&existing).Error; err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error al guardar los cambios",
"error": true,
})
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "Usuario actualizado con éxito",
"error": false,
"user": existing,
})
}
// ACTUALIZAR
func UpdatePassword(c *fiber.Ctx) error {
var m models.Users
uid, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "ID inválido",
"error": true,
})
}
// Analiza el cuerpo de la solicitud
if err := c.BodyParser(&m); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Error al analizar el cuerpo de la solicitud",
"error": true,
})
}
m.ID = uint(uid)
// Verifica si hay un nuevo password para actualizar
if m.Password != "" {
// Crea una instancia de Hash
hash := config.Hash{}
// Encripta la nueva contraseña
hashedPassword, err := hash.Create(m.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
m.Password = hashedPassword
// Actualiza solo el campo de contraseña en la base de datos
if err := models.UpdateUserPassword(m.ID, m.Password); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err.Error(),
"error": true,
})
}
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "Contraseña actualizada con éxito",
"error": false,
})
}
// CREAR
func CreateUser(c *fiber.Ctx) error {
var m models.Users
// Analiza el cuerpo de la solicitud
if err := c.BodyParser(&m); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Error al analizar el cuerpo de la solicitud",
"error": true,
})
}
m.TipoUsuario = "sistema"
estado := true
m.Estado = &estado
m.EmailVerified = true
// Crea el nuevo módulo en la base de datos
if err := models.CreateUser(m); err != nil { // Asegúrate de tener una función para crear un módulo
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err.Error(),
"error": true,
})
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{
"message": "Usuario creado con éxito",
"error": false,
"user": m,
})
}
// ELIMINAR
func DeleteUser(c *fiber.Ctx) error {
uid, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid ID",
"error": true,
})
}
if err := models.DeleteUser(uint(uid)); err != nil { // Ensure you have a function for deleting a module
return c.JSON(fiber.Map{
"message": err.Error(),
"error": true,
})
}
return c.JSON(fiber.Map{
"message": "Usuario eliminado correctamente",
"error": false,
})
}
func CreateUserGas(c *fiber.Ctx) error {
var m models.Users
// Analiza el cuerpo de la solicitud
if err := c.BodyParser(&m); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Error al analizar el cuerpo de la solicitud",
"error": true,
})
}
// Verifica si el nombre de usuario ya existe
exists, err := models.CheckUsernameExists(m.NombreUsuario)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error al verificar el nombre de usuario",
"error": err.Error(),
})
}
if exists {
return c.Status(fiber.StatusConflict).JSON(fiber.Map{
"message": "El codigo ya se encuentra registrado",
"error": true,
})
}
// Debug: imprimir los datos que se pasan a GetValidarMedidor
fmt.Println("Llamando a GetValidarMedidor con NombreUsuario:", m.NombreUsuario, "y NumeroMedidor:", m.NumeroMedidor)
// Aquí llamamos a la función GetValidarMedidor pasándole el código y medidor directamente desde el cuerpo de la solicitud
// Obtén el RoleID basado en el RoleName
roleName := "Usuarios"
role, err := models.FindRoleByName(roleName)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error al obtener el rol",
"error": err.Error(),
})
}
// Asigna el RoleID al usuario
m.RoleID = role.ID
m.TipoUsuario = "gas"
estado := true
m.Estado = &estado
m.Password = ""
// Crea el nuevo usuario en la base de datos (sin asignar el ID manualmente)
if err := models.CreateUser(m); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err.Error(),
"error": true,
})
}
user, err := models.GetUserByUsuarioVerify(m.NombreUsuario)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error retrieving user",
"error": err.Error(),
})
}
// Aquí el modelo `m` debe tener el ID generado por la base de datos
fmt.Println("Nuevo usuario creado con ID:", user.ID)
// Llama a la función createPassword pasando el ID del nuevo usuario
if err := createPassword(c, user.ID); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error al actualizar la contraseña",
"error": true,
})
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{
"message": "Usuario creado con éxito",
"error": false,
"user": m,
})
}
func createPassword(c *fiber.Ctx, UserId uint) error {
// Modelo para recibir los datos del cuerpo de la solicitud
type PasswordUpdateRequest struct {
Password string `json:"password"`
}
var req PasswordUpdateRequest
// Analiza el cuerpo de la solicitud
fmt.Println("Recibiendo solicitud para actualizar contraseña...")
if err := c.BodyParser(&req); err != nil {
fmt.Println("Error al analizar el cuerpo de la solicitud:", err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Error al analizar el cuerpo de la solicitud",
"error": true,
})
}
// Verifica si el password no está vacío
if req.Password == "" {
fmt.Println("La contraseña no puede estar vacía")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "La contraseña no puede estar vacía",
"error": true,
})
}
// Crea una instancia del encriptador de contraseñas
hash := config.Hash{}
// Encripta la nueva contraseña
fmt.Println("Encriptando la contraseña...")
hashedPassword, err := hash.Create(req.Password)
if err != nil {
fmt.Println("Error al encriptar la contraseña:", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error al encriptar la contraseña",
"error": true,
})
}
fmt.Println("Contraseña encriptada con éxito.")
// Actualiza solo el campo de contraseña en la base de datos
fmt.Printf("Actualizando la contraseña del usuario con ID %d\n", UserId)
if err := models.UpdateUserPassword(UserId, hashedPassword); err != nil {
fmt.Println("Error al actualizar la contraseña en la base de datos:", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error al actualizar la contraseña en la base de datos",
"error": true,
})
}
// Respuesta de éxito
fmt.Println("Contraseña actualizada con éxito.")
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "Contraseña actualizada con éxito",
"error": false,
})
}
func EnviarCredencialesUsuario(c *fiber.Ctx) error {
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
}
user, err := models.FindUserByID(uint(id))
if err != nil || user == nil {
return c.Status(404).JSON(fiber.Map{"error": "Usuario no encontrado"})
}
if user.Email == "" {
return c.Status(400).JSON(fiber.Map{"error": "El usuario no tiene email registrado"})
}
go services.SendUserCredencialesEmail(user.Email, user.Name, user.NombreUsuario)
return c.JSON(fiber.Map{"ok": true, "message": "Credenciales enviadas a " + user.Email})
}