278 lines
8.1 KiB
Go
278 lines
8.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"web-giao-ban-go/config"
|
|
"web-giao-ban-go/db"
|
|
"web-giao-ban-go/license"
|
|
"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
|
|
}
|
|
|
|
// Handle License Key
|
|
if input.License.Key == "" {
|
|
input.License.Key = current.License.Key
|
|
}
|
|
|
|
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.",
|
|
})
|
|
}
|
|
|
|
// GET /api/license/status
|
|
func HandleGetLicenseStatus(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
status := license.GetStatus()
|
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"success": true,
|
|
"data": status,
|
|
})
|
|
}
|
|
|
|
// POST /api/license/activate
|
|
func HandleActivateLicense(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
var body struct {
|
|
Key string `json:"key"`
|
|
}
|
|
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 JSON không hợp lệ: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
key := strings.TrimSpace(body.Key)
|
|
if key == "" {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"success": false,
|
|
"message": "Vui lòng nhập chuỗi key bản quyền (chỉ nhập chuỗi mã hóa DECODE)",
|
|
})
|
|
return
|
|
}
|
|
|
|
info, err := license.Activate(key)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"success": false,
|
|
"message": "Kích hoạt thất bại: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"success": true,
|
|
"message": fmt.Sprintf("Kích hoạt bản quyền thành công cho đơn vị '%s' (Mã BV: %s)!", info.TenBV, info.Mabvbh),
|
|
"data": info,
|
|
})
|
|
}
|