first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:35:24 +03:00
commit bbbf76b184
592 changed files with 246870 additions and 0 deletions

View File

@@ -0,0 +1,451 @@
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 = &copyright
}
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"})
}