This commit is contained in:
@@ -67,6 +67,7 @@ func AutoMigrate(db *gorm.DB) error {
|
||||
&models.StaffGitHubRepo{},
|
||||
&models.SystemSetting{},
|
||||
&models.GuideLink{},
|
||||
&models.AppDownload{},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
148
server/internal/handlers/handlers_app_downloads.go
Normal file
148
server/internal/handlers/handlers_app_downloads.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"server/internal/models"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// GET /api/public/app-downloads
|
||||
func ListAppDownloadsPublicHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
var apps []models.AppDownload
|
||||
if err := db.Order("created_at desc").Find(&apps).Error; err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Không thể tải danh sách ứng dụng"})
|
||||
}
|
||||
return c.JSON(fiber.Map{"data": apps})
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/app-downloads
|
||||
func ListAppDownloadsHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
var apps []models.AppDownload
|
||||
if err := db.Order("created_at desc").Find(&apps).Error; err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Không thể tải danh sách ứng dụng"})
|
||||
}
|
||||
return c.JSON(fiber.Map{"data": apps})
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/app-downloads
|
||||
func CreateAppDownloadHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
if !isSuperAdmin(c) {
|
||||
return c.Status(403).JSON(fiber.Map{"error": "Bạn không có quyền thực hiện chức năng này"})
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
DownloadURL string `json:"downloadUrl"`
|
||||
Platform string `json:"platform"`
|
||||
}
|
||||
var req Request
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Invalid request body"})
|
||||
}
|
||||
if req.Name == "" || req.DownloadURL == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Tên ứng dụng và đường dẫn tải không được để trống"})
|
||||
}
|
||||
|
||||
app := models.AppDownload{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
DownloadURL: req.DownloadURL,
|
||||
Platform: req.Platform,
|
||||
}
|
||||
if err := db.Create(&app).Error; err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Lưu ứng dụng thất bại"})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{"ok": true, "data": app})
|
||||
}
|
||||
}
|
||||
|
||||
// PUT /api/app-downloads/:id
|
||||
func UpdateAppDownloadHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
if !isSuperAdmin(c) {
|
||||
return c.Status(403).JSON(fiber.Map{"error": "Bạn không có quyền thực hiện chức năng này"})
|
||||
}
|
||||
|
||||
idParam := c.Params("id")
|
||||
id, err := strconv.ParseUint(idParam, 10, 32)
|
||||
if err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Invalid ID"})
|
||||
}
|
||||
|
||||
var app models.AppDownload
|
||||
if err := db.First(&app, uint(id)).Error; err != nil {
|
||||
return c.Status(404).JSON(fiber.Map{"error": "Không tìm thấy ứng dụng"})
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
DownloadURL string `json:"downloadUrl"`
|
||||
Platform string `json:"platform"`
|
||||
}
|
||||
var req Request
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Invalid request body"})
|
||||
}
|
||||
if req.Name == "" || req.DownloadURL == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Tên ứng dụng và đường dẫn tải không được để trống"})
|
||||
}
|
||||
|
||||
app.Name = req.Name
|
||||
app.Description = req.Description
|
||||
app.DownloadURL = req.DownloadURL
|
||||
app.Platform = req.Platform
|
||||
|
||||
if err := db.Save(&app).Error; err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Cập nhật ứng dụng thất bại"})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{"ok": true, "data": app})
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE /api/app-downloads/:id
|
||||
func DeleteAppDownloadHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
if !isSuperAdmin(c) {
|
||||
return c.Status(403).JSON(fiber.Map{"error": "Bạn không có quyền thực hiện chức năng này"})
|
||||
}
|
||||
|
||||
idParam := c.Params("id")
|
||||
id, err := strconv.ParseUint(idParam, 10, 32)
|
||||
if err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Invalid ID"})
|
||||
}
|
||||
|
||||
var app models.AppDownload
|
||||
if err := db.First(&app, uint(id)).Error; err != nil {
|
||||
return c.Status(404).JSON(fiber.Map{"error": "Không tìm thấy ứng dụng"})
|
||||
}
|
||||
|
||||
if err := db.Delete(&app).Error; err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Xóa ứng dụng thất bại"})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/public/guide-links
|
||||
func ListGuideLinksPublicHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
var links []models.GuideLink
|
||||
if err := db.Order("created_at desc").Find(&links).Error; err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Không thể tải danh sách tài liệu"})
|
||||
}
|
||||
return c.JSON(fiber.Map{"data": links})
|
||||
}
|
||||
}
|
||||
@@ -199,4 +199,17 @@ type GuideLink struct {
|
||||
|
||||
func (GuideLink) TableName() string { return "guide_links" }
|
||||
|
||||
// AppDownload đại diện cho ứng dụng và link tải
|
||||
type AppDownload struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Name string `gorm:"column:name;size:255;not null" json:"name"`
|
||||
Description string `gorm:"column:description;size:512" json:"description"`
|
||||
DownloadURL string `gorm:"column:download_url;size:1024;not null" json:"downloadUrl"`
|
||||
Platform string `gorm:"column:platform;size:64" json:"platform"` // "Windows", "macOS", "Linux", "Khác"
|
||||
}
|
||||
|
||||
func (AppDownload) TableName() string { return "app_downloads" }
|
||||
|
||||
|
||||
|
||||
@@ -107,6 +107,9 @@ func main() {
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
})
|
||||
|
||||
api.Get("/public/app-downloads", handlers.ListAppDownloadsPublicHandler(gormDB))
|
||||
api.Get("/public/guide-links", handlers.ListGuideLinksPublicHandler(gormDB))
|
||||
|
||||
// Management — yêu cầu đăng nhập staff
|
||||
staff := api.Group("", middleware.RequireStaff())
|
||||
staff.Get("/auth/me", handlers.MeStaffHandler(gormDB))
|
||||
@@ -207,6 +210,11 @@ func main() {
|
||||
staff.Put("/guide-links/:id", handlers.UpdateGuideLinkHandler(gormDB))
|
||||
staff.Delete("/guide-links/:id", handlers.DeleteGuideLinkHandler(gormDB))
|
||||
|
||||
staff.Get("/app-downloads", handlers.ListAppDownloadsHandler(gormDB))
|
||||
staff.Post("/app-downloads", handlers.CreateAppDownloadHandler(gormDB))
|
||||
staff.Put("/app-downloads/:id", handlers.UpdateAppDownloadHandler(gormDB))
|
||||
staff.Delete("/app-downloads/:id", handlers.DeleteAppDownloadHandler(gormDB))
|
||||
|
||||
go func() {
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
@@ -215,6 +223,8 @@ func main() {
|
||||
}
|
||||
}()
|
||||
|
||||
app.Static("/", "../landing_page")
|
||||
|
||||
port := getEnv("PORT", "8080")
|
||||
log.Printf("Server starting on port %s...", port)
|
||||
if err := app.Listen(":" + port); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user