Files
web-giao-ban/handlers/admin.go
T

219 lines
6.4 KiB
Go

package handlers
import (
"encoding/json"
"net/http"
"strconv"
"strings"
"web-giao-ban-go/config"
"web-giao-ban-go/db"
"web-giao-ban-go/logger"
"web-giao-ban-go/updater"
)
// GET /api/admin/config
func HandleGetAdminConfig(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
cfg := config.Get()
// Mask sensitive fields
respCfg := *cfg
if respCfg.Server.AdminPassword != "" {
respCfg.Server.AdminPassword = "••••••••"
}
if respCfg.Database.Password != "" {
respCfg.Database.Password = "••••••••"
}
if respCfg.Updater.Token != "" {
respCfg.Updater.Token = "••••••••"
}
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"data": respCfg,
})
}
// POST /api/admin/config
func HandleSaveAdminConfig(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
var input config.AppConfig
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]interface{}{"success": false, "message": "JSON không hợp lệ: " + err.Error()})
return
}
current := config.Get()
// Handle Admin Password
if input.Server.AdminPassword == "" || input.Server.AdminPassword == "••••••••" {
input.Server.AdminPassword = current.Server.AdminPassword
input.DecryptedAdminPassword = current.DecryptedAdminPassword
} else {
input.DecryptedAdminPassword = input.Server.AdminPassword
enc, _ := config.Encrypt(input.Server.AdminPassword)
input.Server.AdminPassword = enc
}
// Handle DB Password
if input.Database.Password == "" || input.Database.Password == "••••••••" {
input.Database.Password = current.Database.Password
input.DecryptedDBPassword = current.DecryptedDBPassword
} else {
input.DecryptedDBPassword = input.Database.Password
enc, _ := config.Encrypt(input.Database.Password)
input.Database.Password = enc
}
// Handle Updater Token
if input.Updater.Token == "" || input.Updater.Token == "••••••••" {
input.Updater.Token = current.Updater.Token
input.DecryptedUpdaterToken = current.DecryptedUpdaterToken
} else {
input.DecryptedUpdaterToken = input.Updater.Token
enc, _ := config.Encrypt(input.Updater.Token)
input.Updater.Token = enc
}
if err := config.SaveConfig(&input); err != nil {
w.WriteHeader(http.StatusInternalServerError)
_ = json.NewEncoder(w).Encode(map[string]interface{}{"success": false, "message": "Lưu file thất bại: " + err.Error()})
return
}
// Reset DB pool to apply new connection parameters
db.CloseAll()
logger.Info("Đã lưu cấu hình mới và làm mới kết nối CSDL")
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"message": "Đã lưu cấu hình và mã hóa mật khẩu thành công!",
})
}
// POST /api/admin/test-db
func HandleTestDBConnection(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
var body struct {
Host string `json:"host"`
Port int `json:"port"`
User string `json:"user"`
Password string `json:"password"`
Database string `json:"database"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]interface{}{"success": false, "message": "Dữ liệu không hợp lệ"})
return
}
cfg := config.Get()
pass := body.Password
if pass == "" || pass == "••••••••" {
pass = cfg.DecryptedDBPassword
}
err := db.TestConnection(body.Host, body.Port, body.User, pass, body.Database)
if err != nil {
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": "Kết nối thất bại: " + err.Error(),
})
return
}
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"message": "Kết nối PostgreSQL thành công!",
})
}
// GET /api/admin/logs
func HandleGetLogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
limitStr := r.URL.Query().Get("limit")
level := r.URL.Query().Get("level")
limit := 100
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 {
limit = l
}
entries := logger.Get().GetEntries(limit, strings.ToUpper(level))
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"data": entries,
})
}
// POST /api/admin/logs/clear
func HandleClearLogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
logger.Get().Clear()
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"message": "Đã làm trống bộ nhớ log!",
})
}
// GET /api/update/check
func HandleCheckUpdate(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
res, err := updater.CheckUpdate()
if err != nil {
logger.Error("Kiểm tra cập nhật lỗi: %v", err)
w.WriteHeader(http.StatusInternalServerError)
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": err.Error(),
})
return
}
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"data": res,
})
}
// POST /api/update/apply
func HandleApplyUpdate(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
var body struct {
AssetURL string `json:"asset_url"`
Version string `json:"version"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.AssetURL == "" {
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]interface{}{"success": false, "message": "Thiếu thông tin URL bản cập nhật"})
return
}
err := updater.ApplyUpdate(body.AssetURL)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": "Cập nhật thất bại: " + err.Error(),
})
return
}
// Update current version in config if provided
if body.Version != "" {
cfg := config.Get()
cfg.Updater.CurrentVersion = body.Version
_ = config.SaveConfig(cfg)
}
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"message": "Đã cập nhật phiên bản mới thành công! Vui lòng khởi động lại phần mềm để áp dụng.",
})
}