Files
jiang13-forum/routers/install/install.go
freefire 118f967540 feat: 发评限流与品牌 Logo/Favicon/OG 上传
发评挂 RateLimiter comment;设置页支持品牌图上传/清除,并写入 favicon 与 og:image。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-30 04:06:48 +08:00

133 lines
3.3 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 install
import (
"net/http"
"strings"
"git.iioio.com/freefire/jiang13-forum/modules/webctx"
"git.iioio.com/freefire/jiang13-forum/services"
"github.com/gin-gonic/gin"
)
// Deps 安装依赖
type Deps struct {
DataDir string
JWTSecret string
Auth *services.AuthService
Settings *services.ForumSettingsService
}
type pageData struct {
Title string
Description string
SiteName string
Slogan string
LogoMark string
LogoURL string
FaviconURL string
OGImageURL string
ShowFriendLinksFooter bool
FooterPages []struct {
Title string
Slug string
}
CSRF string
Error string
Flash string
AdminUsername string
AdminEmail string
AdminNickname string
}
// Register 未安装时的路由(仅 /install
func Register(r *gin.Engine, deps Deps) {
r.GET("/install", deps.Get)
r.POST("/install", deps.Post)
}
// Get 安装页
func (d Deps) Get(c *gin.Context) {
if services.IsInstalled(d.DataDir) {
c.Redirect(http.StatusFound, "/")
return
}
ctx := webctx.New(c, d.JWTSecret)
brand := d.Settings.SiteBranding()
name := brand.Name
if name == "" {
name = "姜十三论坛"
}
ctx.HTML(http.StatusOK, "install", pageData{
Title: "安装 · " + name, SiteName: name, LogoMark: "姜",
CSRF: ctx.EnsureCSRF(), AdminUsername: "admin",
})
}
// Post 提交安装
func (d Deps) Post(c *gin.Context) {
if services.IsInstalled(d.DataDir) {
c.Redirect(http.StatusSeeOther, "/")
return
}
ctx := webctx.New(c, d.JWTSecret)
brand := d.Settings.SiteBranding()
siteName := strings.TrimSpace(c.PostForm("site_name"))
if siteName == "" {
siteName = "姜十三论坛"
}
data := pageData{
Title: "安装 · " + siteName, SiteName: siteName, LogoMark: "姜",
CSRF: ctx.EnsureCSRF(),
AdminUsername: strings.TrimSpace(c.PostForm("admin_username")),
AdminEmail: strings.TrimSpace(c.PostForm("admin_email")),
AdminNickname: strings.TrimSpace(c.PostForm("admin_nickname")),
}
if !ctx.CheckCSRF() {
data.Error = "无效请求,请重试"
ctx.HTML(http.StatusBadRequest, "install", data)
return
}
pass := c.PostForm("admin_password")
pass2 := c.PostForm("admin_password2")
if pass != pass2 {
data.Error = "两次密码不一致"
ctx.HTML(http.StatusBadRequest, "install", data)
return
}
if _, err := d.Auth.CreateAdmin(data.AdminUsername, pass, data.AdminNickname, data.AdminEmail); err != nil {
data.Error = err.Error()
ctx.HTML(http.StatusBadRequest, "install", data)
return
}
b := d.Settings.SiteBranding()
b.Name = siteName
_ = d.Settings.UpdateSiteBranding(b)
if err := services.WriteInstallLock(d.DataDir); err != nil {
data.Error = "写入安装锁失败: " + err.Error()
ctx.HTML(http.StatusInternalServerError, "install", data)
return
}
ctx.HTML(http.StatusOK, "post-install", pageData{
Title: "安装完成", SiteName: siteName, LogoMark: "姜",
})
_ = brand
}
// Guard 未安装则只允许 install / assets / health
func Guard(dataDir string) gin.HandlerFunc {
return func(c *gin.Context) {
if services.IsInstalled(dataDir) {
c.Next()
return
}
path := c.Request.URL.Path
if path == "/install" || path == "/health" ||
strings.HasPrefix(path, "/ssr-assets/") {
c.Next()
return
}
c.Redirect(http.StatusFound, "/install")
c.Abort()
}
}