Files
jiang13-bbs/backend/service/bg.go
freefire d784b0ea7a feat: 交付官方 Docker 运行时,外观改背景图并下线自定义 CSS/JS
站点/后台分轨背景与用户列表排序一并落地;生产 CORS 改走 SITE_URL,健康检查带版本号。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 05:27:33 +08:00

168 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"errors"
"path/filepath"
"regexp"
"strings"
)
// 站点背景图(前台 / 后台分轨)
const (
SettingKeyBgSiteURL = "bg_site_url"
SettingKeyBgSiteMode = "bg_site_mode"
SettingKeyBgAdminURL = "bg_admin_url"
SettingKeyBgAdminMode = "bg_admin_mode"
BgSurfaceSite = "site"
BgSurfaceAdmin = "admin"
BgModeCover = "cover"
BgModeContain = "contain"
BgModeRepeat = "repeat"
BgModeRepeatX = "repeat-x"
BgModeRepeatY = "repeat-y"
BgModeStretch = "stretch"
BgModeCenter = "center"
DefaultBgMode = BgModeCover
)
// ErrBgFileMissing 设置了合法 URL 但磁盘上没有对应文件
var ErrBgFileMissing = errors.New("背景图文件不存在")
// 仅接受本站上传目录下的 32 位 hex 文件名,禁止外链与路径穿越(写入 CSS url())
var bgUploadURLRe = regexp.MustCompile(`^/uploads/backgrounds/[0-9a-f]{32}\.(jpg|jpeg|png|webp)$`)
var bgModes = map[string]struct{}{
BgModeCover: {},
BgModeContain: {},
BgModeRepeat: {},
BgModeRepeatX: {},
BgModeRepeatY: {},
BgModeStretch: {},
BgModeCenter: {},
}
// NormalizeBgMode 校验铺放模式;空串视为默认 cover
func NormalizeBgMode(raw string) (string, bool) {
m := strings.ToLower(strings.TrimSpace(raw))
if m == "" {
return DefaultBgMode, true
}
if _, ok := bgModes[m]; !ok {
return "", false
}
return m, true
}
// NormalizeBgURL 校验背景图 URL;空串表示清除(走默认画布)
func NormalizeBgURL(raw string) (string, bool) {
u := strings.TrimSpace(raw)
if u == "" {
return "", true
}
u = strings.ToLower(u)
if !bgUploadURLRe.MatchString(u) {
return "", false
}
return u, true
}
// NormalizeBgSurface 前台 site / 后台 admin
func NormalizeBgSurface(raw string) (string, bool) {
s := strings.ToLower(strings.TrimSpace(raw))
if s == BgSurfaceSite || s == BgSurfaceAdmin {
return s, true
}
return "", false
}
func (s *SettingService) BgSiteURL() (string, error) {
return s.bgURL(SettingKeyBgSiteURL)
}
func (s *SettingService) BgAdminURL() (string, error) {
return s.bgURL(SettingKeyBgAdminURL)
}
func (s *SettingService) BgSiteMode() (string, error) {
return s.bgMode(SettingKeyBgSiteMode)
}
func (s *SettingService) BgAdminMode() (string, error) {
return s.bgMode(SettingKeyBgAdminMode)
}
func (s *SettingService) bgURL(key string) (string, error) {
v, found, err := s.getValue(key)
if err != nil || !found {
return "", err
}
u, ok := NormalizeBgURL(v)
if !ok {
return "", nil
}
return u, nil
}
func (s *SettingService) bgMode(key string) (string, error) {
v, found, err := s.getValue(key)
if err != nil || !found {
return DefaultBgMode, err
}
m, ok := NormalizeBgMode(v)
if !ok {
return DefaultBgMode, nil
}
return m, nil
}
// SetBgSiteURL 保存前台背景;空串删除键
func (s *SettingService) SetBgSiteURL(url string) error {
return s.setBgURL(SettingKeyBgSiteURL, url)
}
// SetBgAdminURL 保存后台背景;空串删除键
func (s *SettingService) SetBgAdminURL(url string) error {
return s.setBgURL(SettingKeyBgAdminURL, url)
}
func (s *SettingService) setBgURL(key, url string) error {
u, ok := NormalizeBgURL(url)
if !ok {
return ErrInvalidSiteSetting
}
if u == "" {
return s.deleteKey(key)
}
return s.putValue(key, u)
}
func (s *SettingService) SetBgSiteMode(mode string) error {
return s.setBgMode(SettingKeyBgSiteMode, mode)
}
func (s *SettingService) SetBgAdminMode(mode string) error {
return s.setBgMode(SettingKeyBgAdminMode, mode)
}
func (s *SettingService) setBgMode(key, mode string) error {
m, ok := NormalizeBgMode(mode)
if !ok {
return ErrInvalidSiteSetting
}
if m == DefaultBgMode {
return s.deleteKey(key)
}
return s.putValue(key, m)
}
// BgRelPath 把合法 URL 转成 uploads 根下的相对路径;非法返回空
func BgRelPath(url string) string {
u, ok := NormalizeBgURL(url)
if !ok || u == "" {
return ""
}
return filepath.FromSlash(strings.TrimPrefix(u, "/uploads/"))
}