290 lines
9.6 KiB
Go
290 lines
9.6 KiB
Go
package controllers
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
|
)
|
|
|
|
// ─── Admin: vista principal ───────────────────────────────────────────────────
|
|
|
|
func PartnerRecursosIndex(c *fiber.Ctx) error {
|
|
return c.Render("partner_recursos", fiber.Map{
|
|
"user": c.Locals("user"),
|
|
"modules": c.Locals("userModules"),
|
|
}, "layouts/main")
|
|
}
|
|
|
|
// ─── Recursos ─────────────────────────────────────────────────────────────────
|
|
|
|
func LoadPartnerRecursos(c *fiber.Ctx) error {
|
|
recursos, err := models.GetAllPartnerRecursos(false)
|
|
if err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(fiber.Map{"recursos": recursos})
|
|
}
|
|
|
|
func CreatePartnerRecurso(c *fiber.Ctx) error {
|
|
type Req struct {
|
|
Nombre string `json:"nombre"`
|
|
Descripcion string `json:"descripcion"`
|
|
Categoria string `json:"categoria"`
|
|
Enlace string `json:"enlace"`
|
|
Activo bool `json:"activo"`
|
|
}
|
|
var req Req
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Datos inválidos"})
|
|
}
|
|
r := &models.PartnerRecurso{
|
|
Nombre: req.Nombre,
|
|
Descripcion: req.Descripcion,
|
|
Categoria: req.Categoria,
|
|
Enlace: req.Enlace,
|
|
Activo: req.Activo,
|
|
}
|
|
if err := models.CreatePartnerRecurso(r); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.Status(201).JSON(r)
|
|
}
|
|
|
|
func UpdatePartnerRecurso(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
type Req struct {
|
|
Nombre string `json:"nombre"`
|
|
Descripcion string `json:"descripcion"`
|
|
Categoria string `json:"categoria"`
|
|
Enlace string `json:"enlace"`
|
|
Activo bool `json:"activo"`
|
|
}
|
|
var req Req
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Datos inválidos"})
|
|
}
|
|
r, err := models.GetPartnerRecursoByID(uint(id))
|
|
if err != nil {
|
|
return c.Status(404).JSON(fiber.Map{"error": "No encontrado"})
|
|
}
|
|
r.Nombre = req.Nombre
|
|
r.Descripcion = req.Descripcion
|
|
r.Categoria = req.Categoria
|
|
r.Enlace = req.Enlace
|
|
r.Activo = req.Activo
|
|
if err := models.UpdatePartnerRecurso(r); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(r)
|
|
}
|
|
|
|
func DeletePartnerRecurso(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
if err := models.DeletePartnerRecurso(uint(id)); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(fiber.Map{"ok": true})
|
|
}
|
|
|
|
func UploadPartnerRecursoArchivo(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
file, err := c.FormFile("archivo")
|
|
if err != nil {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Archivo requerido"})
|
|
}
|
|
if file.Size > 50*1024*1024 {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Máximo 50MB"})
|
|
}
|
|
dir := "uploads/partner_recursos"
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": "Error al crear directorio"})
|
|
}
|
|
safeFile := safeFilenameProyecto(file.Filename)
|
|
savePath := filepath.Join(dir, fmt.Sprintf("%d_%s", id, safeFile))
|
|
// Validar que la ruta quede dentro de uploads/
|
|
clean := filepath.Clean(savePath)
|
|
if !strings.HasPrefix(clean, "uploads/") {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Ruta inválida"})
|
|
}
|
|
if err := c.SaveFile(file, savePath); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": "Error al guardar archivo"})
|
|
}
|
|
r, err := models.GetPartnerRecursoByID(uint(id))
|
|
if err != nil {
|
|
return c.Status(404).JSON(fiber.Map{"error": "Recurso no encontrado"})
|
|
}
|
|
r.Archivo = savePath
|
|
r.NombreOrig = file.Filename
|
|
if err := models.UpdatePartnerRecurso(r); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(fiber.Map{"ok": true, "archivo": savePath, "nombre_orig": file.Filename})
|
|
}
|
|
|
|
func DownloadPartnerRecurso(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
r, err := models.GetPartnerRecursoByID(uint(id))
|
|
if err != nil || r.Archivo == "" {
|
|
return c.Status(404).JSON(fiber.Map{"error": "Archivo no encontrado"})
|
|
}
|
|
clean := filepath.Clean(r.Archivo)
|
|
if !strings.HasPrefix(clean, "uploads/") {
|
|
return c.Status(403).JSON(fiber.Map{"error": "Acceso denegado"})
|
|
}
|
|
nombre := r.NombreOrig
|
|
if nombre == "" {
|
|
nombre = filepath.Base(r.Archivo)
|
|
}
|
|
c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, nombre))
|
|
return c.SendFile(clean)
|
|
}
|
|
|
|
// ─── Comunicados ──────────────────────────────────────────────────────────────
|
|
|
|
func LoadPartnerComunicados(c *fiber.Ctx) error {
|
|
items, err := models.GetAllPartnerComunicados(false)
|
|
if err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(fiber.Map{"comunicados": items})
|
|
}
|
|
|
|
func CreatePartnerComunicado(c *fiber.Ctx) error {
|
|
type Req struct {
|
|
Titulo string `json:"titulo"`
|
|
Contenido string `json:"contenido"`
|
|
Activo bool `json:"activo"`
|
|
}
|
|
var req Req
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Datos inválidos"})
|
|
}
|
|
item := &models.PartnerComunicado{
|
|
Titulo: req.Titulo,
|
|
Contenido: req.Contenido,
|
|
Activo: req.Activo,
|
|
}
|
|
if err := models.CreatePartnerComunicado(item); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.Status(201).JSON(item)
|
|
}
|
|
|
|
func UpdatePartnerComunicado(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
type Req struct {
|
|
Titulo string `json:"titulo"`
|
|
Contenido string `json:"contenido"`
|
|
Activo bool `json:"activo"`
|
|
}
|
|
var req Req
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Datos inválidos"})
|
|
}
|
|
item, err := models.GetPartnerComunicadoByID(uint(id))
|
|
if err != nil {
|
|
return c.Status(404).JSON(fiber.Map{"error": "No encontrado"})
|
|
}
|
|
item.Titulo = req.Titulo
|
|
item.Contenido = req.Contenido
|
|
item.Activo = req.Activo
|
|
if err := models.UpdatePartnerComunicado(item); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(item)
|
|
}
|
|
|
|
func DeletePartnerComunicado(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
if err := models.DeletePartnerComunicado(uint(id)); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(fiber.Map{"ok": true})
|
|
}
|
|
|
|
func UploadPartnerComunicadoArchivo(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
file, err := c.FormFile("archivo")
|
|
if err != nil {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Archivo requerido"})
|
|
}
|
|
if file.Size > 50*1024*1024 {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Máximo 50MB"})
|
|
}
|
|
dir := "uploads/partner_comunicados"
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": "Error al crear directorio"})
|
|
}
|
|
safeFile := safeFilenameProyecto(file.Filename)
|
|
savePath := filepath.Join(dir, fmt.Sprintf("%d_%s", id, safeFile))
|
|
clean := filepath.Clean(savePath)
|
|
if !strings.HasPrefix(clean, "uploads/") {
|
|
return c.Status(400).JSON(fiber.Map{"error": "Ruta inválida"})
|
|
}
|
|
if err := c.SaveFile(file, savePath); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": "Error al guardar archivo"})
|
|
}
|
|
item, err := models.GetPartnerComunicadoByID(uint(id))
|
|
if err != nil {
|
|
return c.Status(404).JSON(fiber.Map{"error": "Comunicado no encontrado"})
|
|
}
|
|
item.Archivo = savePath
|
|
item.NombreOrig = file.Filename
|
|
if err := models.UpdatePartnerComunicado(item); err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(fiber.Map{"ok": true, "archivo": savePath, "nombre_orig": file.Filename})
|
|
}
|
|
|
|
func DownloadPartnerComunicadoArchivo(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
item, err := models.GetPartnerComunicadoByID(uint(id))
|
|
if err != nil || item.Archivo == "" {
|
|
return c.Status(404).JSON(fiber.Map{"error": "Archivo no encontrado"})
|
|
}
|
|
clean := filepath.Clean(item.Archivo)
|
|
if !strings.HasPrefix(clean, "uploads/") {
|
|
return c.Status(403).JSON(fiber.Map{"error": "Acceso denegado"})
|
|
}
|
|
nombre := item.NombreOrig
|
|
if nombre == "" {
|
|
nombre = filepath.Base(item.Archivo)
|
|
}
|
|
c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, nombre))
|
|
return c.SendFile(clean)
|
|
}
|
|
|
|
// ─── Portal: acceso para partners ────────────────────────────────────────────
|
|
|
|
func PortalPartnerRecursos(c *fiber.Ctx) error {
|
|
recursos, _ := models.GetAllPartnerRecursos(true)
|
|
comunicados, _ := models.GetAllPartnerComunicados(true)
|
|
return c.JSON(fiber.Map{
|
|
"recursos": recursos,
|
|
"comunicados": comunicados,
|
|
})
|
|
}
|
|
|
|
func PortalDownloadPartnerRecurso(c *fiber.Ctx) error {
|
|
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
|
r, err := models.GetPartnerRecursoByID(uint(id))
|
|
if err != nil || r.Archivo == "" || !r.Activo {
|
|
return c.Status(404).JSON(fiber.Map{"error": "Archivo no encontrado"})
|
|
}
|
|
clean := filepath.Clean(r.Archivo)
|
|
if !strings.HasPrefix(clean, "uploads/") {
|
|
return c.Status(403).JSON(fiber.Map{"error": "Acceso denegado"})
|
|
}
|
|
nombre := r.NombreOrig
|
|
if nombre == "" {
|
|
nombre = filepath.Base(r.Archivo)
|
|
}
|
|
c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, nombre))
|
|
return c.SendFile(clean)
|
|
}
|