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 } // Realiza la actualización de los campos seleccionados if err := models.UpdateUser(m.ID, m.Name, m.NombreUsuario, m.Email, int(m.RoleID)); 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}) }