- Created servidor_dashboard.html with beautiful visual dashboard - Shows all servers in grid cards with basic info - Click button opens detailed modal with: - Server full information (IP, CPU, RAM, Storage, OS, Expiration) - All connected databases in a clean diagram layout - Database connection status (active/inactive) - Connection details (Host, Port, User, Type) - Ping button to test connection with response time - View Connection button to open query-runner - Backend updates: - Added ServidorDashboard() controller to render the dashboard view - Added GetServidorDashboard() API endpoint to fetch server + connections - Added PingConexion() endpoint to test database connections (TCP + DB test) - Color-coded status badges and database type indicators - Responsive design for mobile and desktop - Routes: - GET /app/servidor-dashboard (render view) - GET /api/app/servidor-dashboard/:id (get server details API) - GET /api/app/conx-ping/:id (ping connection endpoint) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
247 lines
6.2 KiB
Go
Executable File
247 lines
6.2 KiB
Go
Executable File
package controllers
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"net"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/sujit-baniya/fiber-boilerplate/app"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
|
|
)
|
|
|
|
// RENDER
|
|
func Servidor(c *fiber.Ctx) error {
|
|
data := fiber.Map{
|
|
"user": c.Locals("user").(map[string]interface{}),
|
|
"modules": c.Locals("userModules"),
|
|
}
|
|
|
|
if err := c.Render("servidor", data, "layouts/main"); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"message": "Error rendering template",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ServidorDashboard renders the server dashboard view
|
|
func ServidorDashboard(c *fiber.Ctx) error {
|
|
data := fiber.Map{
|
|
"user": c.Locals("user").(map[string]interface{}),
|
|
"modules": c.Locals("userModules"),
|
|
}
|
|
|
|
if err := c.Render("servidor_dashboard", data, "layouts/main"); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"message": "Error rendering template",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetServidor(c *fiber.Ctx) error {
|
|
pageStr := c.Query("page", "1")
|
|
page, err := strconv.Atoi(pageStr)
|
|
if err != nil || page < 1 {
|
|
page = 1
|
|
}
|
|
searchQuery := c.Query("search", "")
|
|
limitStr := c.Query("limit", "10")
|
|
limit, _ := strconv.Atoi(limitStr)
|
|
offset := (page - 1) * limit
|
|
|
|
records, total, err := models.GetAllServidores(limit, offset, searchQuery)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"message": "Error retrieving records",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
totalPages := int(math.Ceil(float64(total) / float64(limit)))
|
|
return c.JSON(fiber.Map{
|
|
"registros": records,
|
|
"total": total,
|
|
"totalPages": totalPages,
|
|
"page": page,
|
|
"limit": limit,
|
|
})
|
|
}
|
|
|
|
func GetServidorSelect(c *fiber.Ctx) error {
|
|
records, err := models.GetAllServidoresSelect()
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"message": "Error retrieving records",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
return c.JSON(fiber.Map{
|
|
"registros": records,
|
|
})
|
|
}
|
|
|
|
func CreateServidor(c *fiber.Ctx) error {
|
|
var m models.Servidor
|
|
|
|
if err := c.BodyParser(&m); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"message": "Error parsing request body",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
if err := models.CreateServidor(m); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"message": "Error creating servidor",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusCreated).JSON(m)
|
|
}
|
|
|
|
func UpdateServidor(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": "ID inválido",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
var m models.Servidor
|
|
|
|
if err := c.BodyParser(&m); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"message": "Error al parsear el cuerpo de la solicitud",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
m.ID = uint(uid)
|
|
|
|
if err := models.UpdateServidor(m); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"message": "Error al actualizar el servidor",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(m)
|
|
}
|
|
|
|
func DeleteServidor(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": "ID inválido",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
var m models.Servidor
|
|
m.ID = uint(uid)
|
|
|
|
if err := models.DeleteServidor(m); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"message": "Error al eliminar el servidor",
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
|
"message": "Servidor eliminado exitosamente",
|
|
})
|
|
}
|
|
|
|
// GetServidorDashboard retorna un servidor con todas sus conexiones de BD
|
|
func GetServidorDashboard(c *fiber.Ctx) error {
|
|
servidorID := c.Params("id")
|
|
uid, err := strconv.ParseUint(servidorID, 10, 32)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"error": "ID inválido",
|
|
})
|
|
}
|
|
|
|
// Obtener servidor
|
|
var servidor models.Servidor
|
|
db := app.Http.Database.DB
|
|
if err := db.Preload("ProvServidor").Preload("TipoServidor").First(&servidor, uid).Error; err != nil {
|
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
|
"error": "Servidor no encontrado",
|
|
})
|
|
}
|
|
|
|
// Obtener conexiones de BD asociadas
|
|
var conexiones []models.ConxDb
|
|
if err := db.Preload("Servidor").Preload("TipoDb").Where("servidor_id = ?", uid).Find(&conexiones).Error; err != nil {
|
|
conexiones = []models.ConxDb{}
|
|
}
|
|
|
|
return c.JSON(fiber.Map{
|
|
"servidor": servidor,
|
|
"conexiones": conexiones,
|
|
})
|
|
}
|
|
|
|
// PingConexion tests the connection to a database and returns the response time
|
|
func PingConexion(c *fiber.Ctx) error {
|
|
conexionID := c.Params("id")
|
|
uid, err := strconv.ParseUint(conexionID, 10, 32)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"exitoso": false,
|
|
"error": "ID inválido",
|
|
})
|
|
}
|
|
|
|
// Obtener conexión de BD
|
|
var conexion models.ConxDb
|
|
db := app.Http.Database.DB
|
|
if err := db.Preload("TipoDb").Preload("Servidor").First(&conexion, uid).Error; err != nil {
|
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
|
"exitoso": false,
|
|
"error": "Conexión no encontrada",
|
|
})
|
|
}
|
|
|
|
// Realizar ping a la conexión
|
|
inicio := time.Now()
|
|
exitoso := false
|
|
var tiempoMs int64
|
|
|
|
// Intentar conexión TCP
|
|
addr := fmt.Sprintf("%s:%s", conexion.Servidor.IpServidor, conexion.Puerto)
|
|
conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
|
|
if err == nil {
|
|
conn.Close()
|
|
exitoso = true
|
|
tiempoMs = time.Since(inicio).Milliseconds()
|
|
}
|
|
|
|
// Si falla TCP, intentar con la BD específica
|
|
if !exitoso {
|
|
inicio = time.Now()
|
|
testErr := services.TestDBConnection(conexion)
|
|
if testErr == nil {
|
|
exitoso = true
|
|
tiempoMs = time.Since(inicio).Milliseconds()
|
|
}
|
|
}
|
|
|
|
return c.JSON(fiber.Map{
|
|
"exitoso": exitoso,
|
|
"tiempo": tiempoMs,
|
|
"host": conexion.Servidor.IpServidor,
|
|
"puerto": conexion.Puerto,
|
|
"tipo": conexion.TipoDb.Nombre,
|
|
})
|
|
}
|