220 lines
6.1 KiB
Go
220 lines
6.1 KiB
Go
package handlers
|
||
|
||
import (
|
||
"fmt"
|
||
"net/http"
|
||
"strings"
|
||
|
||
"software-download-center/database"
|
||
"software-download-center/utils"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
// GetDatabaseInfo 获取数据库信息
|
||
func GetDatabaseInfo(c *gin.Context) {
|
||
dbType := database.GetDBType()
|
||
osInfo := utils.GetOSInfo()
|
||
|
||
var dbInfo gin.H
|
||
if dbType == "mysql" {
|
||
dbInfo = gin.H{
|
||
"type": "MySQL",
|
||
"status": "connected",
|
||
}
|
||
} else {
|
||
dbInfo = gin.H{
|
||
"type": "SQLite",
|
||
"status": "connected",
|
||
"file": "data/app.db",
|
||
"cgo_support": osInfo.IsCGO,
|
||
}
|
||
}
|
||
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"database": dbInfo,
|
||
"os": gin.H{
|
||
"os": osInfo.OS,
|
||
"arch": osInfo.Arch,
|
||
},
|
||
})
|
||
}
|
||
|
||
// ConvertDatabaseRequest 数据库转换请求
|
||
type ConvertDatabaseRequest struct {
|
||
TargetType string `json:"target_type" binding:"required,oneof=sqlite mysql"`
|
||
}
|
||
|
||
// ConvertDatabase 转换数据库
|
||
func ConvertDatabase(c *gin.Context) {
|
||
var req ConvertDatabaseRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"error": "请求参数错误: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
logger := utils.NewLogger()
|
||
|
||
if err := database.ConvertDatabase(req.TargetType, logger); err != nil {
|
||
AddLog("ERROR", fmt.Sprintf("数据库转换失败: %s", err.Error()))
|
||
c.JSON(http.StatusInternalServerError, gin.H{
|
||
"error": "数据库转换失败: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
AddLog("INFO", fmt.Sprintf("数据库转换成功: %s", req.TargetType))
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"message": fmt.Sprintf("数据库已成功转换为 %s", strings.ToUpper(req.TargetType)),
|
||
"type": req.TargetType,
|
||
})
|
||
}
|
||
|
||
// UpdateDatabasePasswordRequest 更新数据库密码请求
|
||
type UpdateDatabasePasswordRequest struct {
|
||
CurrentPassword string `json:"current_password" binding:"required"`
|
||
NewPassword string `json:"new_password" binding:"required,min=1"`
|
||
ConfirmPassword string `json:"confirm_password" binding:"required"`
|
||
}
|
||
|
||
// UpdateDatabasePassword 更新数据库 root 密码
|
||
func UpdateDatabasePassword(c *gin.Context) {
|
||
var req UpdateDatabasePasswordRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
AddLog("WARN", fmt.Sprintf("更新数据库密码请求参数错误: %s (IP: %s)", err.Error(), c.ClientIP()))
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"error": "请求参数错误: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 验证新密码和确认密码是否一致
|
||
if req.NewPassword != req.ConfirmPassword {
|
||
AddLog("WARN", fmt.Sprintf("更新数据库密码失败(密码不一致)(IP: %s)", c.ClientIP()))
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"error": "新密码和确认密码不一致",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 检查当前数据库类型
|
||
dbType := database.GetDBType()
|
||
if dbType != "mysql" {
|
||
AddLog("WARN", fmt.Sprintf("更新数据库密码失败(当前数据库不是 MySQL)(IP: %s)", c.ClientIP()))
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"error": "当前数据库类型不是 MySQL,无法修改密码",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 验证当前密码
|
||
if err := database.VerifyMySQLPassword(req.CurrentPassword); err != nil {
|
||
AddLog("WARN", fmt.Sprintf("更新数据库密码失败(当前密码验证失败)(IP: %s)", c.ClientIP()))
|
||
c.JSON(http.StatusUnauthorized, gin.H{
|
||
"error": "当前密码错误",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 更新密码
|
||
if err := database.UpdateMySQLPassword(req.NewPassword); err != nil {
|
||
AddLog("ERROR", fmt.Sprintf("更新数据库密码失败: %s (IP: %s)", err.Error(), c.ClientIP()))
|
||
c.JSON(http.StatusInternalServerError, gin.H{
|
||
"error": "更新密码失败: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
AddLog("INFO", fmt.Sprintf("数据库 root 密码更新成功 (IP: %s)", c.ClientIP()))
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"message": "数据库密码更新成功!请更新环境变量 DB_PASSWORD 并重启服务器以使新密码生效。",
|
||
})
|
||
}
|
||
|
||
// GetDatabaseConfig 获取数据库配置信息(不包含敏感信息)
|
||
func GetDatabaseConfig(c *gin.Context) {
|
||
config := database.GetDatabaseConfig()
|
||
|
||
// 隐藏敏感信息
|
||
safeConfig := gin.H{
|
||
"type": config.Type,
|
||
"host": config.Host,
|
||
"port": config.Port,
|
||
"user": config.User,
|
||
"database": config.Database,
|
||
"table_prefix": config.TablePrefix,
|
||
"has_password": config.Password != "",
|
||
}
|
||
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"config": safeConfig,
|
||
})
|
||
}
|
||
|
||
// UpdateDatabaseConfigRequest 更新数据库配置请求
|
||
type UpdateDatabaseConfigRequest struct {
|
||
Type string `json:"type" binding:"required,oneof=sqlite mysql"`
|
||
Host string `json:"host"`
|
||
Port string `json:"port"`
|
||
User string `json:"user"`
|
||
Password string `json:"password"`
|
||
Database string `json:"database"`
|
||
TablePrefix string `json:"table_prefix"`
|
||
DSN string `json:"dsn"`
|
||
}
|
||
|
||
// UpdateDatabaseConfig 更新数据库配置(需要重新连接)
|
||
func UpdateDatabaseConfig(c *gin.Context) {
|
||
var req UpdateDatabaseConfigRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"error": "请求参数错误: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 验证必填字段
|
||
if req.Type == "mysql" {
|
||
if req.Host == "" || req.Port == "" || req.User == "" || req.Database == "" {
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"error": "MySQL 配置不完整:需要 host, port, user, database",
|
||
})
|
||
return
|
||
}
|
||
} else if req.Type == "sqlite" {
|
||
if req.DSN == "" {
|
||
req.DSN = "data"
|
||
}
|
||
}
|
||
|
||
// 构建数据库配置
|
||
config := &database.DatabaseConfig{
|
||
Type: req.Type,
|
||
Host: req.Host,
|
||
Port: req.Port,
|
||
User: req.User,
|
||
Password: req.Password,
|
||
Database: req.Database,
|
||
TablePrefix: req.TablePrefix,
|
||
DSN: req.DSN,
|
||
}
|
||
|
||
// 测试连接
|
||
if err := database.InitDBWithConfig(config); err != nil {
|
||
AddLog("ERROR", fmt.Sprintf("数据库配置更新失败: %s (IP: %s)", err.Error(), c.ClientIP()))
|
||
c.JSON(http.StatusInternalServerError, gin.H{
|
||
"error": "数据库连接失败: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
AddLog("INFO", fmt.Sprintf("数据库配置更新成功: 类型=%s (IP: %s)", req.Type, c.ClientIP()))
|
||
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"message": "数据库配置已更新,请重启服务器以应用更改",
|
||
"type": req.Type,
|
||
})
|
||
}
|