335 lines
7.6 KiB
Go
335 lines
7.6 KiB
Go
package controller
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/sirupsen/logrus"
|
|
"hy2xs-admin/dao"
|
|
"hy2xs-admin/model/bo"
|
|
"hy2xs-admin/model/constant"
|
|
"hy2xs-admin/model/dto"
|
|
"hy2xs-admin/model/entity"
|
|
"hy2xs-admin/model/vo"
|
|
"hy2xs-admin/service"
|
|
"hy2xs-admin/util"
|
|
"io"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func isOrchestratorManagedConfigKey(key string) bool {
|
|
switch key {
|
|
case constant.HUIWebPort,
|
|
constant.HUIWebContext,
|
|
constant.HUICrtPath,
|
|
constant.HUIKeyPath,
|
|
constant.Hysteria2Enable,
|
|
constant.Hysteria2Config,
|
|
constant.Hysteria2TrafficStatsSecret:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func UpdateConfigs(c *gin.Context) {
|
|
configsUpdateDto, err := validateField(c, dto.ConfigsUpdateDto{})
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
port, crtPath, keyPath, err := service.GetPortAndCert()
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
|
|
needRestart := false
|
|
|
|
for _, item := range configsUpdateDto.ConfigUpdateDtos {
|
|
key := *item.Key
|
|
value := *item.Value
|
|
|
|
if isOrchestratorManagedConfigKey(key) {
|
|
vo.Fail(fmt.Sprintf("%s managed by orchestrator: use hy2xs-orchestrator reconfigure", key), c)
|
|
return
|
|
}
|
|
|
|
if key == constant.HUIWebPort && strconv.FormatInt(port, 10) != value {
|
|
port, err := strconv.Atoi(value)
|
|
if err != nil {
|
|
vo.Fail(fmt.Sprintf("port: %s is invalid", value), c)
|
|
return
|
|
}
|
|
if !util.IsPortAvailable(uint(port), "tcp") {
|
|
vo.Fail(fmt.Sprintf("port: %s is used", value), c)
|
|
return
|
|
}
|
|
needRestart = true
|
|
}
|
|
if key == constant.HUICrtPath && crtPath != value {
|
|
if value != "" && !util.Exists(value) {
|
|
vo.Fail(fmt.Sprintf("crt path: %s is not exist", value), c)
|
|
return
|
|
}
|
|
needRestart = true
|
|
}
|
|
if key == constant.HUIKeyPath && keyPath != value {
|
|
if value != "" && !util.Exists(value) {
|
|
vo.Fail(fmt.Sprintf("key path: %s is not exist", value), c)
|
|
return
|
|
}
|
|
needRestart = true
|
|
}
|
|
|
|
if key == constant.HUIWebContext {
|
|
huiWebContext, err := service.GetConfig(constant.HUIWebContext)
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
if *huiWebContext.Value != value {
|
|
needRestart = true
|
|
}
|
|
}
|
|
|
|
if key == constant.ResetTrafficCron {
|
|
resetTrafficCron, err := service.GetConfig(constant.ResetTrafficCron)
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
if *resetTrafficCron.Value != value {
|
|
needRestart = true
|
|
}
|
|
}
|
|
|
|
if err = service.UpdateConfig(key, value); err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
}
|
|
|
|
if needRestart {
|
|
go func() {
|
|
_ = service.StopServer()
|
|
}()
|
|
}
|
|
|
|
vo.Success(nil, c)
|
|
}
|
|
|
|
func GetConfig(c *gin.Context) {
|
|
configDto, err := validateField(c, dto.ConfigDto{})
|
|
if err != nil {
|
|
return
|
|
}
|
|
config, err := service.GetConfig(*configDto.Key)
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
configVo := vo.ConfigVo{
|
|
Key: *config.Key,
|
|
Value: *config.Value,
|
|
}
|
|
|
|
running := service.Hysteria2IsRunning()
|
|
if *config.Key == constant.Hysteria2Enable {
|
|
if running {
|
|
configVo.Value = "1"
|
|
} else {
|
|
configVo.Value = "0"
|
|
}
|
|
}
|
|
|
|
vo.Success(configVo, c)
|
|
}
|
|
|
|
func ListConfig(c *gin.Context) {
|
|
configsDto, err := validateField(c, dto.ConfigsDto{})
|
|
if err != nil {
|
|
return
|
|
}
|
|
configs, err := service.ListConfig(configsDto.Keys)
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
var configVos []vo.ConfigVo
|
|
for _, item := range configs {
|
|
configVo := vo.ConfigVo{
|
|
Key: *item.Key,
|
|
Value: *item.Value,
|
|
}
|
|
configVos = append(configVos, configVo)
|
|
}
|
|
vo.Success(configVos, c)
|
|
}
|
|
|
|
func GetHysteria2Config(c *gin.Context) {
|
|
config, err := service.GetHysteria2Config()
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
vo.Success(config, c)
|
|
}
|
|
|
|
func UpdateHysteria2Config(c *gin.Context) {
|
|
vo.Fail("managed by orchestrator: use hy2xs-orchestrator reconfigure", c)
|
|
}
|
|
|
|
func ExportHysteria2Config(c *gin.Context) {
|
|
hysteria2ServerConfig, err := service.GetHysteria2Config()
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
|
|
// Значения по умолчанию
|
|
config, err := dao.ListConfig("key in ?", []string{constant.HUIWebPort, constant.Hysteria2TrafficStatsSecret})
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
|
|
var hUIWebPort string
|
|
var trafficStatsSecret string
|
|
for _, item := range config {
|
|
if *item.Key == constant.HUIWebPort {
|
|
hUIWebPort = *item.Value
|
|
} else if *item.Key == constant.Hysteria2TrafficStatsSecret {
|
|
trafficStatsSecret = *item.Value
|
|
}
|
|
}
|
|
|
|
if hUIWebPort == "" || trafficStatsSecret == "" {
|
|
logrus.Errorf("hUIWebPort or trafficStatsSecret is nil")
|
|
vo.Fail(constant.SysError, c)
|
|
return
|
|
}
|
|
|
|
authHttpUrl, err := service.GetAuthHttpUrl()
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
|
|
authType := "http"
|
|
authHttpInsecure := true
|
|
var auth bo.ServerConfigAuth
|
|
auth.Type = &authType
|
|
var http bo.ServerConfigAuthHTTP
|
|
http.URL = &authHttpUrl
|
|
http.Insecure = &authHttpInsecure
|
|
auth.HTTP = &http
|
|
hysteria2ServerConfig.Auth = &auth
|
|
hysteria2ServerConfig.TrafficStats.Secret = &trafficStatsSecret
|
|
|
|
fileName := fmt.Sprintf("Hysteria2Config-%s.yaml", time.Now().Format("20060102150405"))
|
|
filePath := filepath.Join(constant.ExportPathDir, fileName)
|
|
|
|
if err = util.ExportFile(filePath, hysteria2ServerConfig, 1); err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
|
|
if !util.Exists(filePath) {
|
|
vo.Fail("file not exist", c)
|
|
return
|
|
}
|
|
c.Header("Content-Type", "application/octet-stream")
|
|
c.Header("Content-Transfer-Encoding", "binary")
|
|
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
|
|
c.File(filePath)
|
|
}
|
|
|
|
func ImportHysteria2Config(c *gin.Context) {
|
|
vo.Fail("managed by orchestrator: use hy2xs-orchestrator reconfigure", c)
|
|
}
|
|
|
|
func ExportConfig(c *gin.Context) {
|
|
configs, err := service.ListConfigNotIn([]string{constant.Hysteria2Config})
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
fileName := fmt.Sprintf("SystemConfig-%s.json", time.Now().Format("20060102150405"))
|
|
filePath := filepath.Join(constant.ExportPathDir, fileName)
|
|
|
|
if err = util.ExportFile(filePath, configs, 0); err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
|
|
if !util.Exists(filePath) {
|
|
vo.Fail("file not exist", c)
|
|
return
|
|
}
|
|
c.Header("Content-Type", "application/octet-stream")
|
|
c.Header("Content-Transfer-Encoding", "binary")
|
|
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
|
|
c.File(filePath)
|
|
}
|
|
|
|
func ImportConfig(c *gin.Context) {
|
|
file, header, err := c.Request.FormFile("file")
|
|
if err != nil {
|
|
vo.Fail(constant.SysError, c)
|
|
return
|
|
}
|
|
if header.Size > 1024*1024*2 {
|
|
vo.Fail("the file is too big", c)
|
|
return
|
|
}
|
|
if !strings.HasSuffix(header.Filename, ".json") {
|
|
vo.Fail("file format not supported", c)
|
|
return
|
|
}
|
|
content, err := io.ReadAll(file)
|
|
if err != nil {
|
|
vo.Fail("json file read err", c)
|
|
return
|
|
}
|
|
var configs []entity.Config
|
|
if err = json.Unmarshal(content, &configs); err != nil {
|
|
vo.Fail("content Unmarshal err", c)
|
|
return
|
|
}
|
|
for _, cfg := range configs {
|
|
if cfg.Key != nil && isOrchestratorManagedConfigKey(*cfg.Key) {
|
|
vo.Fail(fmt.Sprintf("%s managed by orchestrator: use hy2xs-orchestrator reconfigure", *cfg.Key), c)
|
|
return
|
|
}
|
|
}
|
|
if err = service.UpsertConfig(configs); err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
go func() {
|
|
_ = service.StopServer()
|
|
}()
|
|
vo.Success(nil, c)
|
|
}
|
|
|
|
func Hysteria2AcmePath(c *gin.Context) {
|
|
hysteria2AcmePathVo, err := service.Hysteria2AcmePath()
|
|
if err != nil {
|
|
vo.Fail(err.Error(), c)
|
|
return
|
|
}
|
|
vo.Success(hysteria2AcmePathVo, c)
|
|
}
|
|
|
|
func RestartServer(c *gin.Context) {
|
|
vo.Fail("managed by orchestrator: use hy2xs-orchestrator reconfigure", c)
|
|
}
|
|
|
|
func UploadCertFile(c *gin.Context) {
|
|
vo.Fail("managed by orchestrator: use hy2xs-orchestrator reconfigure", c)
|
|
}
|