first commit
This commit is contained in:
747
app/settings/controllers/settings.go
Normal file
747
app/settings/controllers/settings.go
Normal file
@@ -0,0 +1,747 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"goaresv3/app/settings/models"
|
||||
"goaresv3/config"
|
||||
)
|
||||
|
||||
type UpsertSettingRequest struct {
|
||||
Title string `json:"title" binding:"required,max=254"`
|
||||
MetaTitle string `json:"meta_title" binding:"required,max=254"`
|
||||
MetaDescription string `json:"meta_description" binding:"required,max=254"`
|
||||
Phone string `json:"phone" binding:"required,max=254"`
|
||||
URL string `json:"url" binding:"required,max=254"`
|
||||
Email string `json:"email" binding:"required,email,max=254"`
|
||||
Facebook string `json:"facebook" binding:"omitempty,max=254"`
|
||||
X string `json:"x" binding:"omitempty,max=254"`
|
||||
Instagram string `json:"instagram" binding:"omitempty,max=254"`
|
||||
Whatsapp string `json:"whatsapp" binding:"omitempty,max=254"`
|
||||
Pinterest string `json:"pinterest" binding:"omitempty,max=254"`
|
||||
Linkedin string `json:"linkedin" binding:"omitempty,max=254"`
|
||||
Slogan string `json:"slogan" binding:"omitempty,max=254"`
|
||||
Address string `json:"address"`
|
||||
Copyright string `json:"copyright" binding:"omitempty,max=254"`
|
||||
MapEmbed string `json:"map_embed"`
|
||||
WLogo string `json:"w_logo"`
|
||||
BLogo string `json:"b_logo"`
|
||||
IsActive bool `json:"is_active"`
|
||||
WWidth int `json:"w_width"`
|
||||
WHeight int `json:"w_height"`
|
||||
WQuality int `json:"w_quality"`
|
||||
WFormat string `json:"w_format" binding:"omitempty,max=10"`
|
||||
BWidth int `json:"b_width"`
|
||||
BHeight int `json:"b_height"`
|
||||
BQuality int `json:"b_quality"`
|
||||
BFormat string `json:"b_format" binding:"omitempty,max=10"`
|
||||
}
|
||||
|
||||
type UpsertHeroRequest struct {
|
||||
Color string `json:"color" binding:"required,max=32"`
|
||||
Title string `json:"title" binding:"omitempty,max=254"`
|
||||
Text1 string `json:"text1" binding:"omitempty,max=254"`
|
||||
Text2 string `json:"text2" binding:"omitempty,max=254"`
|
||||
Text4 string `json:"text4" binding:"omitempty,max=254"`
|
||||
Text5 string `json:"text5" binding:"omitempty,max=254"`
|
||||
Image string `json:"image" binding:"omitempty,max=254"`
|
||||
IsActive bool `json:"is_active"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
Quality int `json:"quality"`
|
||||
Format string `json:"format" binding:"omitempty,max=10"`
|
||||
}
|
||||
|
||||
type UpsertCorsWhitelistRequest struct {
|
||||
Origin string `json:"origin" binding:"required,max=255"`
|
||||
Description string `json:"description" binding:"omitempty,max=255"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedBy string `json:"created_by" binding:"omitempty,max=255"`
|
||||
}
|
||||
|
||||
type UpsertCorsBlacklistRequest struct {
|
||||
Origin string `json:"origin" binding:"required,max=255"`
|
||||
Reason string `json:"reason" binding:"omitempty,max=255"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedBy string `json:"created_by" binding:"omitempty,max=255"`
|
||||
}
|
||||
|
||||
type UpsertRateLimitRequest struct {
|
||||
Name string `json:"name" binding:"required,max=100"`
|
||||
Description string `json:"description" binding:"omitempty,max=255"`
|
||||
MaxRequests int64 `json:"max_requests" binding:"required,min=1"`
|
||||
WindowSeconds int `json:"window_seconds" binding:"required,min=1"`
|
||||
IsActive bool `json:"is_active"`
|
||||
UpdatedBy string `json:"updated_by" binding:"omitempty,max=255"`
|
||||
}
|
||||
|
||||
func parseID(c *gin.Context) (uint64, bool) {
|
||||
id, err := strconv.ParseUint(strings.TrimSpace(c.Param("id")), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"})
|
||||
return 0, false
|
||||
}
|
||||
return id, true
|
||||
}
|
||||
|
||||
// GetSetting godoc
|
||||
// @Summary Get global setting
|
||||
// @Description Returns the latest settings record.
|
||||
// @Tags Settings
|
||||
// @Produce json
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings [get]
|
||||
func GetSetting(c *gin.Context) {
|
||||
var setting models.Setting
|
||||
err := config.DB.Order("id DESC").First(&setting).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "setting not found"})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch setting"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, setting)
|
||||
}
|
||||
|
||||
// UpsertSetting godoc
|
||||
// @Summary Create or update global setting
|
||||
// @Description Creates the first setting record if none exists, otherwise updates the latest one.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body UpsertSettingRequest true "setting payload"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Success 201 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings [put]
|
||||
func UpsertSetting(c *gin.Context) {
|
||||
var req UpsertSettingRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var setting models.Setting
|
||||
err := config.DB.Order("id DESC").First(&setting).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
setting = models.Setting{
|
||||
Title: req.Title,
|
||||
MetaTitle: req.MetaTitle,
|
||||
MetaDescription: req.MetaDescription,
|
||||
Phone: req.Phone,
|
||||
URL: req.URL,
|
||||
Email: req.Email,
|
||||
Facebook: req.Facebook,
|
||||
X: req.X,
|
||||
Instagram: req.Instagram,
|
||||
Whatsapp: req.Whatsapp,
|
||||
Pinterest: req.Pinterest,
|
||||
Linkedin: req.Linkedin,
|
||||
Slogan: req.Slogan,
|
||||
Address: req.Address,
|
||||
Copyright: req.Copyright,
|
||||
MapEmbed: req.MapEmbed,
|
||||
WLogo: req.WLogo,
|
||||
BLogo: req.BLogo,
|
||||
IsActive: req.IsActive,
|
||||
WWidth: req.WWidth,
|
||||
WHeight: req.WHeight,
|
||||
WQuality: req.WQuality,
|
||||
WFormat: req.WFormat,
|
||||
BWidth: req.BWidth,
|
||||
BHeight: req.BHeight,
|
||||
BQuality: req.BQuality,
|
||||
BFormat: req.BFormat,
|
||||
}
|
||||
if createErr := config.DB.Create(&setting).Error; createErr != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create setting"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, setting)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch setting"})
|
||||
return
|
||||
}
|
||||
|
||||
updates := map[string]any{
|
||||
"title": req.Title,
|
||||
"meta_title": req.MetaTitle,
|
||||
"meta_description": req.MetaDescription,
|
||||
"phone": req.Phone,
|
||||
"url": req.URL,
|
||||
"email": req.Email,
|
||||
"facebook": req.Facebook,
|
||||
"x": req.X,
|
||||
"instagram": req.Instagram,
|
||||
"whatsapp": req.Whatsapp,
|
||||
"pinterest": req.Pinterest,
|
||||
"linkedin": req.Linkedin,
|
||||
"slogan": req.Slogan,
|
||||
"address": req.Address,
|
||||
"copyright": req.Copyright,
|
||||
"map_embed": req.MapEmbed,
|
||||
"w_logo": req.WLogo,
|
||||
"b_logo": req.BLogo,
|
||||
"is_active": req.IsActive,
|
||||
"w_width": req.WWidth,
|
||||
"w_height": req.WHeight,
|
||||
"w_quality": req.WQuality,
|
||||
"w_format": req.WFormat,
|
||||
"b_width": req.BWidth,
|
||||
"b_height": req.BHeight,
|
||||
"b_quality": req.BQuality,
|
||||
"b_format": req.BFormat,
|
||||
}
|
||||
if err := config.DB.Model(&setting).Updates(updates).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update setting"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := config.DB.First(&setting, setting.ID).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch updated setting"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, setting)
|
||||
}
|
||||
|
||||
// ListHeroes godoc
|
||||
// @Summary List heroes
|
||||
// @Description Returns all hero records ordered by id desc.
|
||||
// @Tags Settings
|
||||
// @Produce json
|
||||
// @Success 200 {array} map[string]interface{}
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/heroes [get]
|
||||
func ListHeroes(c *gin.Context) {
|
||||
var heroes []models.Hero
|
||||
if err := config.DB.Order("id DESC").Find(&heroes).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch heroes"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, heroes)
|
||||
}
|
||||
|
||||
// CreateHero godoc
|
||||
// @Summary Create hero
|
||||
// @Description Creates a new hero record.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body UpsertHeroRequest true "hero payload"
|
||||
// @Success 201 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/heroes [post]
|
||||
func CreateHero(c *gin.Context) {
|
||||
var req UpsertHeroRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
hero := models.Hero{
|
||||
Color: req.Color,
|
||||
Title: req.Title,
|
||||
Text1: req.Text1,
|
||||
Text2: req.Text2,
|
||||
Text4: req.Text4,
|
||||
Text5: req.Text5,
|
||||
Image: req.Image,
|
||||
IsActive: req.IsActive,
|
||||
Width: req.Width,
|
||||
Height: req.Height,
|
||||
Quality: req.Quality,
|
||||
Format: req.Format,
|
||||
}
|
||||
if err := config.DB.Create(&hero).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create hero"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, hero)
|
||||
}
|
||||
|
||||
// UpdateHero godoc
|
||||
// @Summary Update hero
|
||||
// @Description Updates a hero by id.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "hero id"
|
||||
// @Param request body UpsertHeroRequest true "hero payload"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/heroes/{id} [put]
|
||||
func UpdateHero(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var req UpsertHeroRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var hero models.Hero
|
||||
if err := config.DB.First(&hero, id).Error; errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "hero not found"})
|
||||
return
|
||||
} else if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch hero"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := config.DB.Model(&hero).Updates(map[string]any{
|
||||
"color": req.Color,
|
||||
"title": req.Title,
|
||||
"text1": req.Text1,
|
||||
"text2": req.Text2,
|
||||
"text4": req.Text4,
|
||||
"text5": req.Text5,
|
||||
"image": req.Image,
|
||||
"is_active": req.IsActive,
|
||||
"width": req.Width,
|
||||
"height": req.Height,
|
||||
"quality": req.Quality,
|
||||
"format": req.Format,
|
||||
}).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update hero"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := config.DB.First(&hero, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch updated hero"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, hero)
|
||||
}
|
||||
|
||||
// DeleteHero godoc
|
||||
// @Summary Delete hero
|
||||
// @Description Deletes a hero by id.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "hero id"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/heroes/{id} [delete]
|
||||
func DeleteHero(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
res := config.DB.Delete(&models.Hero{}, id)
|
||||
if res.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete hero"})
|
||||
return
|
||||
}
|
||||
if res.RowsAffected == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "hero not found"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "hero deleted"})
|
||||
}
|
||||
|
||||
// ListCorsWhitelists godoc
|
||||
// @Summary List CORS whitelist items
|
||||
// @Description Returns all CORS whitelist records.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Success 200 {array} map[string]interface{}
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/cors/whitelist [get]
|
||||
func ListCorsWhitelists(c *gin.Context) {
|
||||
var items []models.CorsWhitelist
|
||||
if err := config.DB.Order("id DESC").Find(&items).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch cors whitelists"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, items)
|
||||
}
|
||||
|
||||
// CreateCorsWhitelist godoc
|
||||
// @Summary Create CORS whitelist item
|
||||
// @Description Creates a new whitelist origin.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body UpsertCorsWhitelistRequest true "cors whitelist payload"
|
||||
// @Success 201 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/v1/settings/cors/whitelist [post]
|
||||
func CreateCorsWhitelist(c *gin.Context) {
|
||||
var req UpsertCorsWhitelistRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
item := models.CorsWhitelist{
|
||||
Origin: req.Origin,
|
||||
Description: req.Description,
|
||||
IsActive: req.IsActive,
|
||||
CreatedBy: req.CreatedBy,
|
||||
}
|
||||
if err := config.DB.Create(&item).Error; err != nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "failed to create cors whitelist"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, item)
|
||||
}
|
||||
|
||||
// UpdateCorsWhitelist godoc
|
||||
// @Summary Update CORS whitelist item
|
||||
// @Description Updates a whitelist origin by id.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "whitelist id"
|
||||
// @Param request body UpsertCorsWhitelistRequest true "cors whitelist payload"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/v1/settings/cors/whitelist/{id} [put]
|
||||
func UpdateCorsWhitelist(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var req UpsertCorsWhitelistRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
var item models.CorsWhitelist
|
||||
if err := config.DB.First(&item, id).Error; errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "cors whitelist not found"})
|
||||
return
|
||||
} else if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch cors whitelist"})
|
||||
return
|
||||
}
|
||||
if err := config.DB.Model(&item).Updates(map[string]any{
|
||||
"origin": req.Origin,
|
||||
"description": req.Description,
|
||||
"is_active": req.IsActive,
|
||||
"created_by": req.CreatedBy,
|
||||
}).Error; err != nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "failed to update cors whitelist"})
|
||||
return
|
||||
}
|
||||
if err := config.DB.First(&item, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch updated cors whitelist"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, item)
|
||||
}
|
||||
|
||||
// DeleteCorsWhitelist godoc
|
||||
// @Summary Delete CORS whitelist item
|
||||
// @Description Deletes a whitelist origin by id.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "whitelist id"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/cors/whitelist/{id} [delete]
|
||||
func DeleteCorsWhitelist(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
res := config.DB.Delete(&models.CorsWhitelist{}, id)
|
||||
if res.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete cors whitelist"})
|
||||
return
|
||||
}
|
||||
if res.RowsAffected == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "cors whitelist not found"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "cors whitelist deleted"})
|
||||
}
|
||||
|
||||
// ListCorsBlacklists godoc
|
||||
// @Summary List CORS blacklist items
|
||||
// @Description Returns all CORS blacklist records.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Success 200 {array} map[string]interface{}
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/cors/blacklist [get]
|
||||
func ListCorsBlacklists(c *gin.Context) {
|
||||
var items []models.CorsBlacklist
|
||||
if err := config.DB.Order("id DESC").Find(&items).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch cors blacklists"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, items)
|
||||
}
|
||||
|
||||
// CreateCorsBlacklist godoc
|
||||
// @Summary Create CORS blacklist item
|
||||
// @Description Creates a new blacklist origin.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body UpsertCorsBlacklistRequest true "cors blacklist payload"
|
||||
// @Success 201 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/v1/settings/cors/blacklist [post]
|
||||
func CreateCorsBlacklist(c *gin.Context) {
|
||||
var req UpsertCorsBlacklistRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
item := models.CorsBlacklist{
|
||||
Origin: req.Origin,
|
||||
Reason: req.Reason,
|
||||
IsActive: req.IsActive,
|
||||
CreatedBy: req.CreatedBy,
|
||||
}
|
||||
if err := config.DB.Create(&item).Error; err != nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "failed to create cors blacklist"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, item)
|
||||
}
|
||||
|
||||
// UpdateCorsBlacklist godoc
|
||||
// @Summary Update CORS blacklist item
|
||||
// @Description Updates a blacklist origin by id.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "blacklist id"
|
||||
// @Param request body UpsertCorsBlacklistRequest true "cors blacklist payload"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/v1/settings/cors/blacklist/{id} [put]
|
||||
func UpdateCorsBlacklist(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var req UpsertCorsBlacklistRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
var item models.CorsBlacklist
|
||||
if err := config.DB.First(&item, id).Error; errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "cors blacklist not found"})
|
||||
return
|
||||
} else if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch cors blacklist"})
|
||||
return
|
||||
}
|
||||
if err := config.DB.Model(&item).Updates(map[string]any{
|
||||
"origin": req.Origin,
|
||||
"reason": req.Reason,
|
||||
"is_active": req.IsActive,
|
||||
"created_by": req.CreatedBy,
|
||||
}).Error; err != nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "failed to update cors blacklist"})
|
||||
return
|
||||
}
|
||||
if err := config.DB.First(&item, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch updated cors blacklist"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, item)
|
||||
}
|
||||
|
||||
// DeleteCorsBlacklist godoc
|
||||
// @Summary Delete CORS blacklist item
|
||||
// @Description Deletes a blacklist origin by id.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "blacklist id"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/cors/blacklist/{id} [delete]
|
||||
func DeleteCorsBlacklist(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
res := config.DB.Delete(&models.CorsBlacklist{}, id)
|
||||
if res.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete cors blacklist"})
|
||||
return
|
||||
}
|
||||
if res.RowsAffected == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "cors blacklist not found"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "cors blacklist deleted"})
|
||||
}
|
||||
|
||||
// ListRateLimits godoc
|
||||
// @Summary List rate limits
|
||||
// @Description Returns all rate-limit settings.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Success 200 {array} map[string]interface{}
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/rate-limits [get]
|
||||
func ListRateLimits(c *gin.Context) {
|
||||
var items []models.RateLimitSetting
|
||||
if err := config.DB.Order("id DESC").Find(&items).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch rate limits"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, items)
|
||||
}
|
||||
|
||||
// CreateRateLimit godoc
|
||||
// @Summary Create rate limit
|
||||
// @Description Creates a new rate-limit setting.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body UpsertRateLimitRequest true "rate limit payload"
|
||||
// @Success 201 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/v1/settings/rate-limits [post]
|
||||
func CreateRateLimit(c *gin.Context) {
|
||||
var req UpsertRateLimitRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
item := models.RateLimitSetting{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
MaxRequests: req.MaxRequests,
|
||||
WindowSeconds: req.WindowSeconds,
|
||||
IsActive: req.IsActive,
|
||||
UpdatedBy: req.UpdatedBy,
|
||||
}
|
||||
if err := config.DB.Create(&item).Error; err != nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "failed to create rate limit"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, item)
|
||||
}
|
||||
|
||||
// UpdateRateLimit godoc
|
||||
// @Summary Update rate limit
|
||||
// @Description Updates a rate-limit setting by id.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "rate limit id"
|
||||
// @Param request body UpsertRateLimitRequest true "rate limit payload"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/v1/settings/rate-limits/{id} [put]
|
||||
func UpdateRateLimit(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var req UpsertRateLimitRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
var item models.RateLimitSetting
|
||||
if err := config.DB.First(&item, id).Error; errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "rate limit not found"})
|
||||
return
|
||||
} else if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch rate limit"})
|
||||
return
|
||||
}
|
||||
if err := config.DB.Model(&item).Updates(map[string]any{
|
||||
"name": req.Name,
|
||||
"description": req.Description,
|
||||
"max_requests": req.MaxRequests,
|
||||
"window_seconds": req.WindowSeconds,
|
||||
"is_active": req.IsActive,
|
||||
"updated_by": req.UpdatedBy,
|
||||
}).Error; err != nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "failed to update rate limit"})
|
||||
return
|
||||
}
|
||||
if err := config.DB.First(&item, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch updated rate limit"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, item)
|
||||
}
|
||||
|
||||
// DeleteRateLimit godoc
|
||||
// @Summary Delete rate limit
|
||||
// @Description Deletes a rate-limit setting by id.
|
||||
// @Tags Settings
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "rate limit id"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/v1/settings/rate-limits/{id} [delete]
|
||||
func DeleteRateLimit(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
res := config.DB.Delete(&models.RateLimitSetting{}, id)
|
||||
if res.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete rate limit"})
|
||||
return
|
||||
}
|
||||
if res.RowsAffected == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "rate limit not found"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "rate limit deleted"})
|
||||
}
|
||||
34
app/settings/models/cors.go
Normal file
34
app/settings/models/cors.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// CorsWhitelist - CORS için izin verilen origin'ler
|
||||
type CorsWhitelist struct {
|
||||
gorm.Model
|
||||
Origin string `gorm:"type:varchar(255);uniqueIndex;not null" json:"origin"`
|
||||
Description string `gorm:"type:varchar(255)" json:"description"`
|
||||
IsActive bool `gorm:"default:true" json:"is_active"`
|
||||
CreatedBy string `gorm:"type:varchar(255)" json:"created_by,omitempty"`
|
||||
}
|
||||
|
||||
// CorsBlacklist - CORS için yasaklanan origin'ler
|
||||
type CorsBlacklist struct {
|
||||
gorm.Model
|
||||
Origin string `gorm:"type:varchar(255);uniqueIndex;not null" json:"origin"`
|
||||
Reason string `gorm:"type:varchar(255)" json:"reason"`
|
||||
IsActive bool `gorm:"default:true" json:"is_active"`
|
||||
CreatedBy string `gorm:"type:varchar(255)" json:"created_by,omitempty"`
|
||||
}
|
||||
|
||||
// RateLimitSetting - Rate limit ayarları
|
||||
type RateLimitSetting struct {
|
||||
gorm.Model
|
||||
Name string `gorm:"type:varchar(100);uniqueIndex;not null" json:"name"` // e.g., "login", "register", "api"
|
||||
Description string `gorm:"type:varchar(255)" json:"description"`
|
||||
MaxRequests int64 `gorm:"not null" json:"max_requests"` // Max istek sayısı
|
||||
WindowSeconds int `gorm:"not null" json:"window_seconds"` // Zaman penceresi (saniye)
|
||||
IsActive bool `gorm:"default:true" json:"is_active"`
|
||||
UpdatedBy string `gorm:"type:varchar(255)" json:"updated_by,omitempty"`
|
||||
}
|
||||
23
app/settings/models/hero.go
Normal file
23
app/settings/models/hero.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Banner model structure
|
||||
// Represents a banner item with optional thumbnail.
|
||||
type Hero struct {
|
||||
gorm.Model
|
||||
Color string `gorm:"type:varchar(32);not null" json:"color" form:"color"`
|
||||
Title string `gorm:"type:varchar(254)" json:"title,omitempty" form:"title"`
|
||||
Text1 string `gorm:"type:varchar(254)" json:"text1,omitempty" form:"text1"`
|
||||
Text2 string `gorm:"type:varchar(254)" json:"text2,omitempty" form:"text2"`
|
||||
Text4 string `gorm:"type:varchar(254)" json:"text4,omitempty" form:"text4"`
|
||||
Text5 string `gorm:"type:varchar(254)" json:"text5,omitempty" form:"text5"`
|
||||
Image string `gorm:"type:varchar(254)" json:"image" form:"image"`
|
||||
IsActive bool `gorm:"default:true" json:"is_active" form:"is_active"`
|
||||
Width int `gorm:"default:0" json:"width" form:"width"`
|
||||
Height int `gorm:"default:0" json:"height" form:"height"`
|
||||
Quality int `gorm:"default:0" json:"quality" form:"quality"`
|
||||
Format string `gorm:"type:varchar(10)" json:"format" form:"format"`
|
||||
}
|
||||
43
app/settings/models/setting.go
Normal file
43
app/settings/models/setting.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Setting model structure
|
||||
// Stores site-wide metadata and contact information.
|
||||
type Setting struct {
|
||||
gorm.Model
|
||||
Title string `gorm:"type:varchar(254);not null" json:"title" form:"title"`
|
||||
MetaTitle string `gorm:"type:varchar(254);not null" json:"meta_title" form:"meta_title"`
|
||||
MetaDescription string `gorm:"type:varchar(254);not null" json:"meta_description" form:"meta_description"`
|
||||
Phone string `gorm:"type:varchar(254);not null" json:"phone" form:"phone"`
|
||||
URL string `gorm:"type:varchar(254);not null" json:"url" form:"url"`
|
||||
Email string `gorm:"type:varchar(254);not null" json:"email" form:"email"`
|
||||
Facebook string `gorm:"type:varchar(254)" json:"facebook,omitempty" form:"facebook"`
|
||||
X string `gorm:"type:varchar(254)" json:"x,omitempty" form:"x"`
|
||||
Instagram string `gorm:"type:varchar(254)" json:"instagram,omitempty" form:"instagram"`
|
||||
Whatsapp string `gorm:"type:varchar(254)" json:"whatsapp,omitempty" form:"whatsapp"`
|
||||
Pinterest string `gorm:"type:varchar(254)" json:"pinterest,omitempty" form:"pinterest"`
|
||||
Linkedin string `gorm:"type:varchar(254)" json:"linkedin,omitempty" form:"linkedin"`
|
||||
Slogan string `gorm:"type:varchar(254)" json:"slogan,omitempty" form:"slogan"`
|
||||
Address string `gorm:"type:text" json:"address,omitempty" form:"address"`
|
||||
Copyright string `gorm:"type:varchar(254)" json:"copyright,omitempty" form:"copyright"`
|
||||
MapEmbed string `gorm:"type:text" json:"map_embed,omitempty" form:"map_embed"`
|
||||
WLogo string `gorm:"type:text" json:"w_logo,omitempty" form:"w_logo"`
|
||||
BLogo string `gorm:"type:text" json:"b_logo,omitempty" form:"b_logo"`
|
||||
IsActive bool `gorm:"default:false" json:"is_active" form:"is_active"`
|
||||
WWidth int `gorm:"default:0" json:"w_width" form:"w_width"`
|
||||
WHeight int `gorm:"default:0" json:"w_height" form:"w_height"`
|
||||
WQuality int `gorm:"default:0" json:"w_quality" form:"w_quality"`
|
||||
WFormat string `gorm:"type:varchar(10)" json:"w_format" form:"w_format"`
|
||||
BWidth int `gorm:"default:0" json:"b_width" form:"b_width"`
|
||||
BHeight int `gorm:"default:0" json:"b_height" form:"b_height"`
|
||||
BQuality int `gorm:"default:0" json:"b_quality" form:"b_quality"`
|
||||
BFormat string `gorm:"type:varchar(10)" json:"b_format" form:"b_format"`
|
||||
}
|
||||
|
||||
// TableName overrides the table name used by Setting to `settings`
|
||||
func (Setting) TableName() string {
|
||||
return "settings"
|
||||
}
|
||||
Reference in New Issue
Block a user