452 lines
13 KiB
Go
452 lines
13 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"gauth-central/config"
|
|
"gauth-central/internal/services"
|
|
"gauth-central/pkg/utils"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type SiteInfoHandler struct {
|
|
siteInfoService *services.SiteInfoService
|
|
}
|
|
|
|
func NewSiteInfoHandler(siteInfoService *services.SiteInfoService) *SiteInfoHandler {
|
|
return &SiteInfoHandler{siteInfoService: siteInfoService}
|
|
}
|
|
|
|
// GetAllSiteInfos godoc
|
|
// @Summary Get all active site info
|
|
// @Description Retrieve a list of active site info entries
|
|
// @Tags site-info
|
|
// @Produce json
|
|
// @Success 200 {array} models.Setting
|
|
// @Failure 500 {object} map[string]string
|
|
// @Router /site-info [get]
|
|
func (h *SiteInfoHandler) GetAllSiteInfos(c *gin.Context) {
|
|
items, err := h.siteInfoService.GetAllSiteInfos(true)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, items)
|
|
}
|
|
|
|
// GetActiveSiteInfo godoc
|
|
// @Summary Get active site info
|
|
// @Description Retrieve the newest active site info entry
|
|
// @Tags site-info
|
|
// @Produce json
|
|
// @Success 200 {object} models.Setting
|
|
// @Failure 404 {object} map[string]string
|
|
// @Router /site-info/active [get]
|
|
func (h *SiteInfoHandler) GetActiveSiteInfo(c *gin.Context) {
|
|
item, err := h.siteInfoService.GetFirstActiveSiteInfo()
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, item)
|
|
}
|
|
|
|
// AdminGetAllSiteInfos godoc
|
|
// @Summary Get all site info (Admin)
|
|
// @Description Retrieve a list of all site info entries including inactive ones
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Produce json
|
|
// @Success 200 {array} models.Setting
|
|
// @Failure 500 {object} map[string]string
|
|
// @Router /admin/site-info [get]
|
|
func (h *SiteInfoHandler) AdminGetAllSiteInfos(c *gin.Context) {
|
|
items, err := h.siteInfoService.GetAllSiteInfos(false)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, items)
|
|
}
|
|
|
|
// AdminGetSiteInfoByID godoc
|
|
// @Summary Get site info by ID (Admin)
|
|
// @Description Retrieve details of a specific site info entry
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Produce json
|
|
// @Param id path string true "Site Info ID"
|
|
// @Success 200 {object} models.Setting
|
|
// @Failure 404 {object} map[string]string
|
|
// @Router /admin/site-info/{id} [get]
|
|
func (h *SiteInfoHandler) AdminGetSiteInfoByID(c *gin.Context) {
|
|
id := c.Param("id")
|
|
item, err := h.siteInfoService.GetSiteInfoByID(id)
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, item)
|
|
}
|
|
|
|
// CreateSiteInfo godoc
|
|
// @Summary Create site info (Admin)
|
|
// @Description Create a new site info entry
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Accept multipart/form-data
|
|
// @Produce json
|
|
// @Param title formData string true "Title"
|
|
// @Param meta_title formData string false "Meta title"
|
|
// @Param meta_description formData string false "Meta description"
|
|
// @Param phone formData string true "Phone"
|
|
// @Param url formData string false "Site URL"
|
|
// @Param email formData string true "Email"
|
|
// @Param facebook formData string false "Facebook"
|
|
// @Param x formData string false "X"
|
|
// @Param instagram formData string false "Instagram"
|
|
// @Param whatsapp formData string false "Whatsapp"
|
|
// @Param pinterest formData string false "Pinterest"
|
|
// @Param linkedin formData string false "LinkedIn"
|
|
// @Param slogan formData string false "Slogan"
|
|
// @Param w_logo formData file false "White logo"
|
|
// @Param b_logo formData file false "Black logo"
|
|
// @Param is_active formData bool false "Is active"
|
|
// @Success 201 {object} models.Setting
|
|
// @Failure 400 {object} map[string]string
|
|
// @Router /admin/site-info [post]
|
|
func (h *SiteInfoHandler) CreateSiteInfo(c *gin.Context) {
|
|
title := strings.TrimSpace(c.PostForm("title"))
|
|
phone := strings.TrimSpace(c.PostForm("phone"))
|
|
email := strings.TrimSpace(c.PostForm("email"))
|
|
if title == "" || phone == "" || email == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "title, phone, and email are required"})
|
|
return
|
|
}
|
|
|
|
metaTitle := strings.TrimSpace(c.PostForm("meta_title"))
|
|
metaDescription := strings.TrimSpace(c.PostForm("meta_description"))
|
|
url := strings.TrimSpace(c.PostForm("url"))
|
|
facebook := strings.TrimSpace(c.PostForm("facebook"))
|
|
xValue := strings.TrimSpace(c.PostForm("x"))
|
|
instagram := strings.TrimSpace(c.PostForm("instagram"))
|
|
whatsapp := strings.TrimSpace(c.PostForm("whatsapp"))
|
|
pinterest := strings.TrimSpace(c.PostForm("pinterest"))
|
|
linkedin := strings.TrimSpace(c.PostForm("linkedin"))
|
|
slogan := strings.TrimSpace(c.PostForm("slogan"))
|
|
address := strings.TrimSpace(c.PostForm("address"))
|
|
copyright := strings.TrimSpace(c.PostForm("copyright"))
|
|
mapEmbed := strings.TrimSpace(c.PostForm("map_embed"))
|
|
|
|
isActive := false
|
|
isActivePtr, err := parseOptionalBool(c, "is_active")
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "is_active must be true or false"})
|
|
return
|
|
}
|
|
if isActivePtr != nil {
|
|
isActive = *isActivePtr
|
|
}
|
|
|
|
wLogo := ""
|
|
wLogoFile, wLogoErr := c.FormFile("w_logo")
|
|
if wLogoErr == nil {
|
|
if wLogoFile.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "w_logo size exceeds 5MB limit"})
|
|
return
|
|
}
|
|
wLogo, err = utils.SaveOptimizedImage(wLogoFile, "./uploads/logo", "wlogo", &utils.ImageOptions{
|
|
Width: config.AppConfig.SettingsLogoWidth,
|
|
Height: config.AppConfig.SettingsLogoHeight,
|
|
Quality: float32(config.AppConfig.SettingsLogoQuality),
|
|
Format: config.AppConfig.SettingsLogoFormat,
|
|
Mode: config.AppConfig.SettingsLogoMode,
|
|
})
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save w_logo: " + err.Error()})
|
|
return
|
|
}
|
|
}
|
|
|
|
bLogo := ""
|
|
bLogoFile, bLogoErr := c.FormFile("b_logo")
|
|
if bLogoErr == nil {
|
|
if bLogoFile.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "b_logo size exceeds 5MB limit"})
|
|
return
|
|
}
|
|
bLogo, err = utils.SaveOptimizedImage(bLogoFile, "./uploads/logo", "blogo", &utils.ImageOptions{
|
|
Width: config.AppConfig.SettingsLogoWidth,
|
|
Height: config.AppConfig.SettingsLogoHeight,
|
|
Quality: float32(config.AppConfig.SettingsLogoQuality),
|
|
Format: config.AppConfig.SettingsLogoFormat,
|
|
Mode: config.AppConfig.SettingsLogoMode,
|
|
})
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save b_logo: " + err.Error()})
|
|
return
|
|
}
|
|
}
|
|
|
|
item, err := h.siteInfoService.CreateSiteInfo(
|
|
title,
|
|
metaTitle,
|
|
metaDescription,
|
|
phone,
|
|
url,
|
|
email,
|
|
facebook,
|
|
xValue,
|
|
instagram,
|
|
whatsapp,
|
|
pinterest,
|
|
linkedin,
|
|
slogan,
|
|
wLogo,
|
|
bLogo,
|
|
isActive,
|
|
address,
|
|
copyright,
|
|
mapEmbed,
|
|
)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, item)
|
|
}
|
|
|
|
// UpdateSiteInfo godoc
|
|
// @Summary Update site info (Admin)
|
|
// @Description Update an existing site info entry
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Accept multipart/form-data
|
|
// @Produce json
|
|
// @Param id path string true "Site Info ID"
|
|
// @Param title formData string false "Title"
|
|
// @Param meta_title formData string false "Meta title"
|
|
// @Param meta_description formData string false "Meta description"
|
|
// @Param phone formData string false "Phone"
|
|
// @Param url formData string false "Site URL"
|
|
// @Param email formData string false "Email"
|
|
// @Param facebook formData string false "Facebook"
|
|
// @Param x formData string false "X"
|
|
// @Param instagram formData string false "Instagram"
|
|
// @Param whatsapp formData string false "Whatsapp"
|
|
// @Param pinterest formData string false "Pinterest"
|
|
// @Param linkedin formData string false "LinkedIn"
|
|
// @Param slogan formData string false "Slogan"
|
|
// @Param w_logo formData file false "White logo"
|
|
// @Param b_logo formData file false "Black logo"
|
|
// @Param is_active formData bool false "Is active"
|
|
// @Success 200 {object} models.Setting
|
|
// @Failure 400 {object} map[string]string
|
|
// @Failure 404 {object} map[string]string
|
|
// @Router /admin/site-info/{id} [put]
|
|
func (h *SiteInfoHandler) UpdateSiteInfo(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
title, hasTitle := getOptionalFormValue(c, "title")
|
|
metaTitle, hasMetaTitle := getOptionalFormValue(c, "meta_title")
|
|
metaDescription, hasMetaDescription := getOptionalFormValue(c, "meta_description")
|
|
phone, hasPhone := getOptionalFormValue(c, "phone")
|
|
url, hasURL := getOptionalFormValue(c, "url")
|
|
email, hasEmail := getOptionalFormValue(c, "email")
|
|
facebook, hasFacebook := getOptionalFormValue(c, "facebook")
|
|
xValue, hasX := getOptionalFormValue(c, "x")
|
|
instagram, hasInstagram := getOptionalFormValue(c, "instagram")
|
|
whatsapp, hasWhatsapp := getOptionalFormValue(c, "whatsapp")
|
|
pinterest, hasPinterest := getOptionalFormValue(c, "pinterest")
|
|
linkedin, hasLinkedin := getOptionalFormValue(c, "linkedin")
|
|
slogan, hasSlogan := getOptionalFormValue(c, "slogan")
|
|
address, hasAddress := getOptionalFormValue(c, "address")
|
|
copyright, hasCopyright := getOptionalFormValue(c, "copyright")
|
|
mapEmbed, hasMapEmbed := getOptionalFormValue(c, "map_embed")
|
|
|
|
var titlePtr *string
|
|
var metaTitlePtr *string
|
|
var metaDescriptionPtr *string
|
|
var phonePtr *string
|
|
var urlPtr *string
|
|
var emailPtr *string
|
|
var facebookPtr *string
|
|
var xPtr *string
|
|
var instagramPtr *string
|
|
var whatsappPtr *string
|
|
var pinterestPtr *string
|
|
var linkedinPtr *string
|
|
var sloganPtr *string
|
|
var addressPtr *string
|
|
var copyrightPtr *string
|
|
var mapEmbedPtr *string
|
|
|
|
if hasTitle {
|
|
titlePtr = &title
|
|
}
|
|
if hasMetaTitle {
|
|
metaTitlePtr = &metaTitle
|
|
}
|
|
if hasMetaDescription {
|
|
metaDescriptionPtr = &metaDescription
|
|
}
|
|
if hasPhone {
|
|
phonePtr = &phone
|
|
}
|
|
if hasURL {
|
|
urlPtr = &url
|
|
}
|
|
if hasEmail {
|
|
emailPtr = &email
|
|
}
|
|
if hasFacebook {
|
|
facebookPtr = &facebook
|
|
}
|
|
if hasX {
|
|
xPtr = &xValue
|
|
}
|
|
if hasInstagram {
|
|
instagramPtr = &instagram
|
|
}
|
|
if hasWhatsapp {
|
|
whatsappPtr = &whatsapp
|
|
}
|
|
if hasPinterest {
|
|
pinterestPtr = &pinterest
|
|
}
|
|
if hasLinkedin {
|
|
linkedinPtr = &linkedin
|
|
}
|
|
if hasSlogan {
|
|
sloganPtr = &slogan
|
|
}
|
|
if hasAddress {
|
|
addressPtr = &address
|
|
}
|
|
if hasCopyright {
|
|
copyrightPtr = ©right
|
|
}
|
|
if hasMapEmbed {
|
|
mapEmbedPtr = &mapEmbed
|
|
}
|
|
|
|
isActivePtr, err := parseOptionalBool(c, "is_active")
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "is_active must be true or false"})
|
|
return
|
|
}
|
|
|
|
var wLogoPtr *string
|
|
wLogoFile, wLogoErr := c.FormFile("w_logo")
|
|
if wLogoErr == nil {
|
|
if wLogoFile.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "w_logo size exceeds 5MB limit"})
|
|
return
|
|
}
|
|
item, fetchErr := h.siteInfoService.GetSiteInfoByID(id)
|
|
if fetchErr != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": fetchErr.Error()})
|
|
return
|
|
}
|
|
if item.WLogo != "" && strings.HasPrefix(item.WLogo, "/uploads/") {
|
|
_ = os.Remove("." + item.WLogo)
|
|
}
|
|
wLogo, saveErr := utils.SaveOptimizedImage(wLogoFile, "./uploads/logo", id+"_w", &utils.ImageOptions{
|
|
Width: config.AppConfig.SettingsLogoWidth,
|
|
Height: config.AppConfig.SettingsLogoHeight,
|
|
Quality: float32(config.AppConfig.SettingsLogoQuality),
|
|
Format: config.AppConfig.SettingsLogoFormat,
|
|
Mode: config.AppConfig.SettingsLogoMode,
|
|
})
|
|
if saveErr != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save w_logo: " + saveErr.Error()})
|
|
return
|
|
}
|
|
wLogoPtr = &wLogo
|
|
}
|
|
|
|
var bLogoPtr *string
|
|
bLogoFile, bLogoErr := c.FormFile("b_logo")
|
|
if bLogoErr == nil {
|
|
if bLogoFile.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "b_logo size exceeds 5MB limit"})
|
|
return
|
|
}
|
|
item, fetchErr := h.siteInfoService.GetSiteInfoByID(id)
|
|
if fetchErr != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": fetchErr.Error()})
|
|
return
|
|
}
|
|
if item.BLogo != "" && strings.HasPrefix(item.BLogo, "/uploads/") {
|
|
_ = os.Remove("." + item.BLogo)
|
|
}
|
|
bLogo, saveErr := utils.SaveOptimizedImage(bLogoFile, "./uploads/logo", id+"_b", &utils.ImageOptions{
|
|
Width: config.AppConfig.SettingsLogoWidth,
|
|
Height: config.AppConfig.SettingsLogoHeight,
|
|
Quality: float32(config.AppConfig.SettingsLogoQuality),
|
|
Format: config.AppConfig.SettingsLogoFormat,
|
|
Mode: config.AppConfig.SettingsLogoMode,
|
|
})
|
|
if saveErr != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save b_logo: " + saveErr.Error()})
|
|
return
|
|
}
|
|
bLogoPtr = &bLogo
|
|
}
|
|
|
|
item, err := h.siteInfoService.UpdateSiteInfo(
|
|
id,
|
|
titlePtr,
|
|
metaTitlePtr,
|
|
metaDescriptionPtr,
|
|
phonePtr,
|
|
urlPtr,
|
|
emailPtr,
|
|
facebookPtr,
|
|
xPtr,
|
|
instagramPtr,
|
|
whatsappPtr,
|
|
pinterestPtr,
|
|
linkedinPtr,
|
|
sloganPtr,
|
|
wLogoPtr,
|
|
bLogoPtr,
|
|
isActivePtr,
|
|
addressPtr,
|
|
copyrightPtr,
|
|
mapEmbedPtr,
|
|
)
|
|
if err != nil {
|
|
status := http.StatusInternalServerError
|
|
if err.Error() == "site info not found" {
|
|
status = http.StatusNotFound
|
|
}
|
|
c.JSON(status, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, item)
|
|
}
|
|
|
|
// DeleteSiteInfo godoc
|
|
// @Summary Delete site info (Admin)
|
|
// @Description Delete a site info entry by ID
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Param id path string true "Site Info ID"
|
|
// @Success 200 {object} map[string]string
|
|
// @Failure 404 {object} map[string]string
|
|
// @Router /admin/site-info/{id} [delete]
|
|
func (h *SiteInfoHandler) DeleteSiteInfo(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if err := h.siteInfoService.DeleteSiteInfo(id); err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"message": "Site info deleted successfully"})
|
|
}
|