up
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sujit-baniya/fiber-boilerplate/app"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VcardApiConfig almacena las credenciales para conectar con la API Admin del
|
||||||
|
// sistema VCard externo (Laravel + Sanctum, prefijo /api/admin/*).
|
||||||
|
type VcardApiConfig struct {
|
||||||
|
gorm.Model
|
||||||
|
Nombre string `json:"nombre" gorm:"column:nombre;not null"`
|
||||||
|
BaseURL string `json:"base_url" gorm:"column:base_url;type:text;not null"`
|
||||||
|
BearerToken string `json:"bearer_token" gorm:"column:bearer_token;type:text;not null"`
|
||||||
|
Activo bool `json:"activo" gorm:"column:activo;default:true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (VcardApiConfig) TableName() string { return "vcard_api_configs" }
|
||||||
|
|
||||||
|
func GetVcardApiConfig() (*VcardApiConfig, error) {
|
||||||
|
var cfg VcardApiConfig
|
||||||
|
if err := app.Http.Database.DB.First(&cfg).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpsertVcardApiConfig(nombre, baseURL, bearerToken string, activo bool) (*VcardApiConfig, error) {
|
||||||
|
var cfg VcardApiConfig
|
||||||
|
err := app.Http.Database.DB.First(&cfg).Error
|
||||||
|
if err != nil {
|
||||||
|
cfg = VcardApiConfig{
|
||||||
|
Nombre: nombre,
|
||||||
|
BaseURL: baseURL,
|
||||||
|
BearerToken: bearerToken,
|
||||||
|
Activo: activo,
|
||||||
|
}
|
||||||
|
if createErr := app.Http.Database.DB.Create(&cfg).Error; createErr != nil {
|
||||||
|
return nil, createErr
|
||||||
|
}
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
||||||
|
cfg.Nombre = nombre
|
||||||
|
cfg.BaseURL = baseURL
|
||||||
|
if bearerToken != "" {
|
||||||
|
cfg.BearerToken = bearerToken
|
||||||
|
}
|
||||||
|
cfg.Activo = activo
|
||||||
|
if err := app.Http.Database.DB.Save(&cfg).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VcardApiIndex renderiza el panel de integración VCard.
|
||||||
|
func VcardApiIndex(c *fiber.Ctx) error {
|
||||||
|
cfg, _ := models.GetVcardApiConfig()
|
||||||
|
data := fiber.Map{
|
||||||
|
"user": c.Locals("user").(map[string]interface{}),
|
||||||
|
"modules": c.Locals("userModules"),
|
||||||
|
"config": cfg,
|
||||||
|
}
|
||||||
|
return c.Render("vcard_api", data, "layouts/main")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VcardApiSaveConfig guarda / actualiza la configuración (base URL + token).
|
||||||
|
func VcardApiSaveConfig(c *fiber.Ctx) error {
|
||||||
|
type Req struct {
|
||||||
|
Nombre string `json:"nombre"`
|
||||||
|
BaseURL string `json:"base_url"`
|
||||||
|
BearerToken string `json:"bearer_token"`
|
||||||
|
Activo bool `json:"activo"`
|
||||||
|
}
|
||||||
|
var req Req
|
||||||
|
if err := c.BodyParser(&req); err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"})
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(req.BaseURL) == "" {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "base_url es requerido"})
|
||||||
|
}
|
||||||
|
cfg, err := models.UpsertVcardApiConfig(req.Nombre, strings.TrimRight(strings.TrimSpace(req.BaseURL), "/"), req.BearerToken, req.Activo)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||||
|
}
|
||||||
|
return c.JSON(fiber.Map{"ok": true, "config": cfg})
|
||||||
|
}
|
||||||
|
|
||||||
|
// VcardApiGetConfig devuelve la configuración actual (sin exponer el token completo).
|
||||||
|
func VcardApiGetConfig(c *fiber.Ctx) error {
|
||||||
|
cfg, err := models.GetVcardApiConfig()
|
||||||
|
if err != nil {
|
||||||
|
return c.JSON(fiber.Map{"config": nil})
|
||||||
|
}
|
||||||
|
masked := "••••••••"
|
||||||
|
if cfg.BearerToken == "" {
|
||||||
|
masked = ""
|
||||||
|
}
|
||||||
|
return c.JSON(fiber.Map{
|
||||||
|
"config": fiber.Map{
|
||||||
|
"ID": cfg.ID,
|
||||||
|
"nombre": cfg.Nombre,
|
||||||
|
"base_url": cfg.BaseURL,
|
||||||
|
"bearer_token": masked,
|
||||||
|
"activo": cfg.Activo,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// vcardDo ejecuta una llamada a la API Admin VCard y devuelve el body como json.RawMessage.
|
||||||
|
func vcardDo(method, endpoint string, cfg *models.VcardApiConfig) ([]byte, int, error) {
|
||||||
|
url := fmt.Sprintf("%s%s", cfg.BaseURL, endpoint)
|
||||||
|
client := &http.Client{Timeout: 15 * time.Second}
|
||||||
|
req, err := http.NewRequest(method, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", "Bearer "+cfg.BearerToken)
|
||||||
|
req.Header.Set("Accept", "application/json")
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, _ := io.ReadAll(io.LimitReader(resp.Body, 512*1024))
|
||||||
|
return body, resp.StatusCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// proxyVcard extrae la config, llama al endpoint y devuelve el resultado al frontend.
|
||||||
|
func proxyVcard(c *fiber.Ctx, method, endpoint string) error {
|
||||||
|
cfg, err := models.GetVcardApiConfig()
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Configura primero la API VCard"})
|
||||||
|
}
|
||||||
|
if !cfg.Activo {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "La integración está inactiva"})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pasar query params del request original
|
||||||
|
qs := string(c.Request().URI().QueryString())
|
||||||
|
ep := endpoint
|
||||||
|
if qs != "" {
|
||||||
|
ep = endpoint + "?" + qs
|
||||||
|
}
|
||||||
|
|
||||||
|
body, status, err := vcardDo(method, ep, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusBadGateway).JSON(fiber.Map{"error": err.Error()})
|
||||||
|
}
|
||||||
|
var result json.RawMessage
|
||||||
|
if err := json.Unmarshal(body, &result); err != nil {
|
||||||
|
result = json.RawMessage(fmt.Sprintf(`{"raw": %q}`, string(body)))
|
||||||
|
}
|
||||||
|
c.Status(status)
|
||||||
|
return c.JSON(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Proxy endpoints ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
func VcardApiUsuarios(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/usuarios")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiUsuario(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/usuarios/"+c.Params("id"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiVcards(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/vcards")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiVcard(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/vcards/"+c.Params("id"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiVcardsByUsuario(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/usuarios/"+c.Params("userId")+"/vcards")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiPlanes(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/planes")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiMembresia(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/usuarios/"+c.Params("id")+"/membresia")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiPagos(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/pagos")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiPagosByUsuario(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/usuarios/"+c.Params("userId")+"/pagos")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiTransacciones(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/transacciones")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiTransaccionesByUsuario(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/usuarios/"+c.Params("userId")+"/transacciones")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiLogs(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiLogsByUsuario(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/usuarios/"+c.Params("userId")+"/logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiMiniwebs(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/miniwebs")
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiMiniweb(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/miniwebs/"+c.Params("id"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func VcardApiMiniwebsByUsuario(c *fiber.Ctx) error {
|
||||||
|
return proxyVcard(c, http.MethodGet, "/api/admin/usuarios/"+c.Params("userId")+"/miniwebs")
|
||||||
|
}
|
||||||
@@ -215,6 +215,27 @@ func UserRoutes(app fiber.Router) {
|
|||||||
protected.Get("/saas-api/logs", middlewares.MenuMiddleware, controllers.SaasDispatchLogIndex)
|
protected.Get("/saas-api/logs", middlewares.MenuMiddleware, controllers.SaasDispatchLogIndex)
|
||||||
protected.Get("/loadsaasdispatchlogs", controllers.GetSaasDispatchLogs)
|
protected.Get("/loadsaasdispatchlogs", controllers.GetSaasDispatchLogs)
|
||||||
|
|
||||||
|
// ─── VCard API (integración Admin Laravel) ────────────────────────────────
|
||||||
|
protected.Get("/vcard-api", middlewares.MenuMiddleware, controllers.VcardApiIndex)
|
||||||
|
protected.Get("/vcard-api/config", controllers.VcardApiGetConfig)
|
||||||
|
protected.Post("/vcard-api/config", controllers.VcardApiSaveConfig)
|
||||||
|
protected.Get("/vcard-api/usuarios", controllers.VcardApiUsuarios)
|
||||||
|
protected.Get("/vcard-api/usuarios/:id/membresia", controllers.VcardApiMembresia)
|
||||||
|
protected.Get("/vcard-api/usuarios/:userId/vcards", controllers.VcardApiVcardsByUsuario)
|
||||||
|
protected.Get("/vcard-api/usuarios/:userId/pagos", controllers.VcardApiPagosByUsuario)
|
||||||
|
protected.Get("/vcard-api/usuarios/:userId/transacciones", controllers.VcardApiTransaccionesByUsuario)
|
||||||
|
protected.Get("/vcard-api/usuarios/:userId/logs", controllers.VcardApiLogsByUsuario)
|
||||||
|
protected.Get("/vcard-api/usuarios/:userId/miniwebs", controllers.VcardApiMiniwebsByUsuario)
|
||||||
|
protected.Get("/vcard-api/usuarios/:id", controllers.VcardApiUsuario)
|
||||||
|
protected.Get("/vcard-api/vcards", controllers.VcardApiVcards)
|
||||||
|
protected.Get("/vcard-api/vcards/:id", controllers.VcardApiVcard)
|
||||||
|
protected.Get("/vcard-api/planes", controllers.VcardApiPlanes)
|
||||||
|
protected.Get("/vcard-api/pagos", controllers.VcardApiPagos)
|
||||||
|
protected.Get("/vcard-api/transacciones", controllers.VcardApiTransacciones)
|
||||||
|
protected.Get("/vcard-api/logs", controllers.VcardApiLogs)
|
||||||
|
protected.Get("/vcard-api/miniwebs", controllers.VcardApiMiniwebs)
|
||||||
|
protected.Get("/vcard-api/miniwebs/:id", controllers.VcardApiMiniweb)
|
||||||
|
|
||||||
// ─── Telegram ─────────────────────────────────────────────────────────────
|
// ─── Telegram ─────────────────────────────────────────────────────────────
|
||||||
protected.Get("/telegram", middlewares.MenuMiddleware, controllers.TelegramIndex)
|
protected.Get("/telegram", middlewares.MenuMiddleware, controllers.TelegramIndex)
|
||||||
protected.Get("/loadtelegram", controllers.GetTelegramConfigs)
|
protected.Get("/loadtelegram", controllers.GetTelegramConfigs)
|
||||||
|
|||||||
Reference in New Issue
Block a user