💩代码改进

This commit is contained in:
coward 2024-03-14 15:23:16 +08:00
parent 91a1e61334
commit 8dfef5192e
23 changed files with 443 additions and 83 deletions

10
go.mod
View File

@ -11,6 +11,8 @@ require (
github.com/google/uuid v1.6.0
github.com/mojocn/base64Captcha v1.3.6
github.com/redis/go-redis/v9 v9.5.1
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/spf13/cast v1.6.0
golang.org/x/crypto v0.21.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
gopkg.in/yaml.v3 v3.0.1
@ -45,14 +47,14 @@ require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.4.3 // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lixh00/loki-client-go v1.0.1 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
@ -66,6 +68,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@ -74,7 +77,6 @@ require (
github.com/prometheus/procfs v0.8.0 // indirect
github.com/prometheus/prometheus v1.8.2-0.20201028100903-3245b3267b24 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
go.uber.org/atomic v1.10.0 // indirect
@ -92,6 +94,6 @@ require (
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 // indirect
google.golang.org/grpc v1.50.1 // indirect
google.golang.org/protobuf v1.30.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

19
go.sum
View File

@ -156,7 +156,6 @@ github.com/cowardmrx/go_aliyun_oss v1.0.7 h1:MCSKUWi4RZnHhwe4fd7VAsgeRXL0kT9z56T
github.com/cowardmrx/go_aliyun_oss v1.0.7/go.mod h1:xz6B8H840TX7yPcgSLUbK7q6nnEsxFutaltR08Aetdg=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -194,6 +193,8 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
@ -473,8 +474,10 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
@ -621,6 +624,8 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
@ -663,7 +668,6 @@ github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHu
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -727,7 +731,6 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
@ -750,6 +753,8 @@ github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@ -1256,8 +1261,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -1,10 +1,15 @@
package api
import (
"encoding/json"
"fmt"
"gitee.ltd/lxh/logger/log"
"github.com/gin-gonic/gin"
"os"
"strings"
"wireguard-dashboard/http/param"
"wireguard-dashboard/model/entity"
"wireguard-dashboard/model/template_data"
"wireguard-dashboard/queues"
"wireguard-dashboard/repository"
"wireguard-dashboard/utils"
@ -55,7 +60,7 @@ func (clients) Save(c *gin.Context) {
_, err := repository.Client().Save(p, info.(*entity.User).Id)
if err != nil {
utils.GinResponse(c).FailedWithMsg("操作失败")
utils.GinResponse(c).FailedWithErr("操作失败", err)
return
}
@ -67,3 +72,176 @@ func (clients) Save(c *gin.Context) {
utils.GinResponse(c).OK()
}
// Delete
// @description: 删除客户端
// @receiver clients
// @param c
func (clients) Delete(c *gin.Context) {
var id = c.Param("id")
if id == "" || id == "undefined" {
utils.GinResponse(c).FailedWithMsg("参数错误")
return
}
if err := repository.Client().Delete(id); err != nil {
utils.GinResponse(c).FailedWithMsg("操作失败")
return
}
utils.GinResponse(c).OK()
}
// Download
// @description: 下载配置文件
// @receiver clients
// @param c
func (clients) Download(c *gin.Context) {
var id = c.Param("id")
if id == "" || id == "undefined" {
utils.GinResponse(c).FailedWithMsg("参数错误")
return
}
data, err := repository.Client().GetById(id)
if err != nil {
utils.GinResponse(c).FailedWithMsg("获取失败")
return
}
var keys template_data.Keys
_ = json.Unmarshal([]byte(data.Keys), &keys)
setting, err := repository.System().GetServerSetting()
if err != nil {
utils.GinResponse(c).FailedWithMsg("获取设置失败")
return
}
// 处理一下数据
execData := template_data.ClientConfig{
PrivateKey: keys.PrivateKey,
IpAllocation: data.IpAllocation,
MTU: setting.MTU,
DNS: strings.Join(setting.DnsServer, ","),
PublicKey: keys.PublicKey,
PresharedKey: keys.PresharedKey,
AllowedIPS: data.AllowedIps,
Endpoint: setting.EndpointAddress,
ListenPort: data.Server.ListenPort,
PersistentKeepalive: setting.PersistentKeepalive,
}
// 不同环境下处理文件路径
var outPath = "/tmp/" + fmt.Sprintf("%s.conf", data.Name)
var templatePath = "./template/wg.client.conf"
if os.Getenv("GIN_MODE") != "release" {
outPath = "E:\\Workspace\\Go\\wireguard-dashboard\\template\\" + fmt.Sprintf("%s.conf", data.Name)
templatePath = "E:\\Workspace\\Go\\wireguard-dashboard\\template\\wg.client.conf"
}
// 渲染数据
parseTemplate, err := utils.Template().Parse(templatePath)
if err != nil {
utils.GinResponse(c).FailedWithMsg("读取模板文件失败")
return
}
err = utils.Template().Execute(parseTemplate, execData, outPath)
if err != nil {
utils.GinResponse(c).FailedWithMsg("文件渲染失败")
return
}
// 输出文件流
c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Disposition", "attachment; filename="+outPath)
c.Header("Content-Transfer-Encoding", "binary")
c.Header("Connection", "keep-alive")
c.File(outPath)
if err = os.Remove(outPath); err != nil {
log.Errorf("删除临时文件失败: %s", err.Error())
}
}
// GenerateQrCode
// @description: 生成客户端信息二维码
// @receiver clients
// @param c
func (clients) GenerateQrCode(c *gin.Context) {
var id = c.Param("id")
if id == "" || id == "undefined" {
utils.GinResponse(c).FailedWithMsg("参数错误")
return
}
data, err := repository.Client().GetById(id)
if err != nil {
utils.GinResponse(c).FailedWithMsg("获取失败")
return
}
var keys template_data.Keys
_ = json.Unmarshal([]byte(data.Keys), &keys)
setting, err := repository.System().GetServerSetting()
if err != nil {
utils.GinResponse(c).FailedWithMsg("获取设置失败")
return
}
// 处理一下数据
execData := template_data.ClientConfig{
PrivateKey: keys.PrivateKey,
IpAllocation: data.IpAllocation,
MTU: setting.MTU,
PublicKey: keys.PublicKey,
PresharedKey: keys.PresharedKey,
AllowedIPS: data.AllowedIps,
Endpoint: setting.EndpointAddress,
ListenPort: data.Server.ListenPort,
PersistentKeepalive: setting.PersistentKeepalive,
}
// 不同环境下处理文件路径
var outPath = "/tmp/" + fmt.Sprintf("%s.conf", data.Name)
var templatePath = "./template/wg.client.conf"
if os.Getenv("GIN_MODE") != "release" {
outPath = "E:\\Workspace\\Go\\wireguard-dashboard\\template\\" + fmt.Sprintf("%s.conf", data.Name)
templatePath = "E:\\Workspace\\Go\\wireguard-dashboard\\template\\wg.client.conf"
}
// 渲染数据
parseTemplate, err := utils.Template().Parse(templatePath)
if err != nil {
utils.GinResponse(c).FailedWithMsg("读取模板文件失败")
return
}
err = utils.Template().Execute(parseTemplate, execData, outPath)
if err != nil {
utils.GinResponse(c).FailedWithMsg("文件渲染失败")
return
}
// 读取文件内容
fileContent, err := os.ReadFile(outPath)
if err != nil {
utils.GinResponse(c).FailedWithMsg("读取文件失败")
return
}
png, err := utils.QRCode().GenerateQrCodeBase64(fileContent, 256)
if err != nil {
utils.GinResponse(c).FailedWithErr("生成二维码失败", err)
return
}
if err = os.Remove(outPath); err != nil {
log.Errorf("删除临时文件失败: %s", err.Error())
}
utils.GinResponse(c).OKWithData(map[string]interface{}{
"qrCode": png,
})
}

View File

@ -4,6 +4,7 @@ import (
"gitee.ltd/lxh/logger/log"
"github.com/gin-gonic/gin"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"strings"
"wireguard-dashboard/http/param"
"wireguard-dashboard/model/entity"
"wireguard-dashboard/queues"
@ -43,7 +44,7 @@ func (server) SaveServer(c *gin.Context) {
}
publicKey := privateKey.PublicKey()
serverInfo := &entity.Server{
IpScope: p.IpScope,
IpScope: strings.Join(p.IpScope, ","),
ListenPort: p.ListenPort,
PrivateKey: privateKey.String(),
PublicKey: publicKey.String(),
@ -82,17 +83,8 @@ func (server) GetServer(c *gin.Context) {
log.Errorf("获取服务端信息失败: %v", err.Error())
}
utils.GinResponse(c).OKWithData(data)
}
// GetGlobalSetting
// @description: 获取全局设置配置
// @receiver server
// @param c
func (server) GetGlobalSetting(c *gin.Context) {
data, err := repository.System().GetServerSetting()
if err != nil {
log.Errorf("获取配置失败: %v", err.Error())
if data.IpScopeStr != "" {
data.IpScope = strings.Split(data.IpScopeStr, ",")
}
utils.GinResponse(c).OKWithData(data)

51
http/api/setting.go Normal file
View File

@ -0,0 +1,51 @@
package api
import (
"gitee.ltd/lxh/logger/log"
"github.com/gin-gonic/gin"
"wireguard-dashboard/http/param"
"wireguard-dashboard/repository"
"wireguard-dashboard/utils"
)
type setting struct{}
func Setting() setting {
return setting{}
}
// GetGlobalSetting
// @description: 获取全局设置配置
// @receiver setting
// @param c
func (setting) GetGlobalSetting(c *gin.Context) {
data, err := repository.System().GetServerSetting()
if err != nil {
log.Errorf("获取配置失败: %v", err.Error())
}
utils.GinResponse(c).OKWithData(data)
}
// SetGlobalServerSetting
// @description: 设置全局服务配置
// @receiver setting
// @param c
func (setting) SetGlobalServerSetting(c *gin.Context) {
var p param.SetSetting
if err := c.ShouldBind(&p); err != nil {
utils.GinResponse(c).FailedWithErr("参数错误", err)
return
}
}
// GetPublicNetworkIP
// @description: 获取当前机器的公网IP
// @receiver setting
// @param c
func (setting) GetPublicNetworkIP(c *gin.Context) {
utils.GinResponse(c).OKWithData(map[string]string{
"IP": utils.Network().GetHostPublicIP(),
})
}

View File

@ -16,9 +16,9 @@ type SaveClient struct {
Name string `json:"name" form:"name" binding:"required"`
Email string `json:"email" form:"email" binding:"omitempty"`
SubnetRange string `json:"subnetRange" form:"subnetRange" binding:"omitempty"`
IpAllocation string `json:"ipAllocation" form:"ipAllocation" binding:"required"`
AllowedIPS string `json:"allowedIPS" form:"allowedIPS" binding:"required"`
ExtraAllowedIPS string `json:"extraAllowedIPS" form:"extraAllowedIPS" binding:"omitempty"`
IpAllocation []string `json:"ipAllocation" form:"ipAllocation" binding:"required"`
AllowedIPS []string `json:"allowedIPS" form:"allowedIPS" binding:"required"`
ExtraAllowedIPS []string `json:"extraAllowedIPS" form:"extraAllowedIPS" binding:"omitempty"`
Endpoint string `json:"endpoint" form:"endpoint" binding:"omitempty"`
UseServerDNS int `json:"useServerDNS" form:"useServerDNS" binding:"required,oneof=1 0"`
EnabledAfterCreation int `json:"enabledAfterCreation" form:"enabledAfterCreation" binding:"required,oneof=1 0"`

View File

@ -1,10 +1,10 @@
package param
type SaveServer struct {
Id string `json:"id" form:"id" binding:"omitempty"` // id
IpScope string `json:"ipScope" form:"ipScope" binding:"required"` // 内网ip范围段
ListenPort int `json:"listenPort" form:"listenPort" binding:"required"` // 监听端口
PostUpScript string `json:"postUpScript" form:"postUpScript" binding:"omitempty"`
PreDownScript string `json:"preDownScript" form:"preDownScript" binding:"omitempty"`
PostDownScript string `json:"postDownScript" form:"postDownScript" binding:"omitempty"`
Id string `json:"id" form:"id" binding:"omitempty"` // id
IpScope []string `json:"ipScope" form:"ipScope" binding:"required"` // 内网ip范围段
ListenPort int `json:"listenPort" form:"listenPort" binding:"required"` // 监听端口
PostUpScript string `json:"postUpScript" form:"postUpScript" binding:"omitempty"`
PreDownScript string `json:"preDownScript" form:"preDownScript" binding:"omitempty"`
PostDownScript string `json:"postDownScript" form:"postDownScript" binding:"omitempty"`
}

8
http/param/setting.go Normal file
View File

@ -0,0 +1,8 @@
package param
// SetSetting
// @description: 设置
type SetSetting struct {
Code string `json:"code" form:"code" binding:"required"`
Data string `json:"data" form:"data" binding:"required"`
}

View File

@ -25,6 +25,7 @@ func main() {
route.UserApi,
route.ServerApi,
route.ClientApi,
route.SettingApi,
)
handler := route.InitRouter()

View File

@ -4,7 +4,7 @@ package entity
// @description: 服务端
type Server struct {
Base
IpScope string `json:"ipScope" gorm:"type:varchar(30);not null;comment:'ip范围'"`
IpScope string `json:"ipScope" gorm:"type:varchar(255);not null;comment:'ip范围'"`
ListenPort int `json:"listenPort" gorm:"type:int(10);not null;comment:'服务监听端口'"`
PrivateKey string `json:"privateKey" gorm:"type:text;not null;comment:'密钥'"`
PublicKey string `json:"publicKey" gorm:"type:text;not null;comment:'公钥'"`
@ -22,20 +22,21 @@ func (*Server) TableName() string {
// @description: 客户端
type Client struct {
Base
ServerId string `json:"serverId" gorm:"type:varchar(36);not null;comment:'服务端id'"`
Name string `json:"name" gorm:"type:varchar(100);not null;comment:'客户端名称'"`
Email string `json:"email" gorm:"type:varchar(100);default null;comment:'联系邮箱'"`
SubnetRange string `json:"subnetRange" gorm:"type:varchar(255);default null;comment:'子网范围'"`
IpAllocation string `json:"ipAllocation" gorm:"type:varchar(30);not null;comment:'客户端ip'"`
AllowedIps string `json:"allowedIps" gorm:"type:varchar(30);not null;comment:'允许访问的ip'"`
ExtraAllowedIps string `json:"extraAllowedIps" gorm:"type:varchar(30);default null;comment:'额外允许的ip范围'"`
Endpoint string `json:"endpoint" gorm:"type:varchar(255);default null;comment:'端点'"`
UseServerDns int `json:"useServerDns" gorm:"type:int(1);default 1;comment:'是否使用服务端dns'"`
EnableAfterCreation int `json:"enableAfterCreation" gorm:"type:int(1);default 1;comment:'是否创建后启用'"`
Keys string `json:"keys" gorm:"type:text;default null;comment:'公钥和密钥的json串'"`
UserId string `json:"userId" gorm:"type:char(36);not null;comment:'创建人id'"`
Enabled bool `json:"enabled" gorm:"type:tinyint(1);default 1;comment:'状态0 - 禁用 | 1 - 正常)'"`
User *User `json:"user" gorm:"foreignKey:UserId"`
ServerId string `json:"serverId" gorm:"type:varchar(36);not null;comment:'服务端id'"`
Name string `json:"name" gorm:"type:varchar(100);not null;comment:'客户端名称'"`
Email string `json:"email" gorm:"type:varchar(100);default null;comment:'联系邮箱'"`
SubnetRange string `json:"subnetRange" gorm:"type:varchar(255);default null;comment:'子网范围'"`
IpAllocation string `json:"ipAllocation" gorm:"type:varchar(255);not null;comment:'客户端ip'"`
AllowedIps string `json:"allowedIps" gorm:"type:varchar(255);not null;comment:'允许访问的ip'"`
ExtraAllowedIps string `json:"extraAllowedIps" gorm:"type:varchar(255);default null;comment:'额外允许的ip范围'"`
Endpoint string `json:"endpoint" gorm:"type:varchar(255);default null;comment:'端点'"`
UseServerDns int `json:"useServerDns" gorm:"type:int(1);default 1;comment:'是否使用服务端dns'"`
EnableAfterCreation int `json:"enableAfterCreation" gorm:"type:int(1);default 1;comment:'是否创建后启用'"`
Keys string `json:"keys" gorm:"type:text;default null;comment:'公钥和密钥的json串'"`
UserId string `json:"userId" gorm:"type:char(36);not null;comment:'创建人id'"`
Enabled bool `json:"enabled" gorm:"type:tinyint(1);default 1;comment:'状态0 - 禁用 | 1 - 正常)'"`
User *User `json:"user" gorm:"foreignKey:UserId"`
Server *Server `json:"server" gorm:"foreignKey:ServerId"`
}
func (*Client) TableName() string {

View File

@ -32,3 +32,16 @@ type Keys struct {
PublicKey string `json:"publicKey"`
PresharedKey string `json:"presharedKey"`
}
type ClientConfig struct {
PrivateKey string `json:"privateKey"`
IpAllocation string `json:"ipAllocation"`
MTU int `json:"MTU"`
DNS string `json:"DNS"`
PublicKey string `json:"publicKey"`
PresharedKey string `json:"presharedKey"`
AllowedIPS string `json:"allowedIPS"`
Endpoint string `json:"endpoint"`
ListenPort int `json:"listenPort"`
PersistentKeepalive int `json:"persistentKeepalive"`
}

View File

@ -10,9 +10,12 @@ type Client struct {
Name string `json:"name"`
Email string `json:"email"`
SubnetRange string `json:"subnetRange"`
IpAllocation string `json:"ipAllocation"`
AllowedIps string `json:"allowedIPS"`
ExtraAllowedIps string `json:"extraAllowedIPS"`
IpAllocation []string `json:"ipAllocation" gorm:"-"`
IpAllocationStr string `json:"-" gorm:"ipAllocationStr"`
AllowedIps []string `json:"allowedIPS" gorm:"-"`
AllowedIpsStr string `json:"-" gorm:"allowedIPSStr"`
ExtraAllowedIps []string `json:"extraAllowedIPS"`
ExtraAllowedIpsStr string `json:"-" gorm:"extraAllowedIPSStr"`
Endpoint string `json:"endpoint"`
UseServerDNS int `json:"useServerDNS"`
EnableAfterCreation int `json:"enableAfterCreation"`

View File

@ -1,11 +1,11 @@
package vo
type ServerSetting struct {
EndpointAddress string `json:"endpointAddress"`
DnsServer string `json:"dnsServer"`
MTU int `json:"MTU"`
PersistentKeepalive int `json:"persistentKeepalive"`
FirewallMark string `json:"firewallMark"`
Table string `json:"table"`
ConfigFilePath string `json:"configFilePath"`
EndpointAddress string `json:"endpointAddress"`
DnsServer []string `json:"dnsServer"`
MTU int `json:"MTU"`
PersistentKeepalive int `json:"persistentKeepalive"`
FirewallMark string `json:"firewallMark"`
Table string `json:"table"`
ConfigFilePath string `json:"configFilePath"`
}

View File

@ -3,12 +3,13 @@ package vo
// Server
// @description: 服务端返回信息
type Server struct {
Id string `json:"id"` // id
IpScope string `json:"ipScope"` // ip范围
ListenPort int `json:"listenPort"` // 服务监听端口
PrivateKey string `json:"privateKey"` // 私钥
PublicKey string `json:"publicKey"` // 公钥
PostUpScript string `json:"postUpScript"`
PreDownScript string `json:"preDownScript"`
PostDownScript string `json:"postDownScript"`
Id string `json:"id"` // id
IpScope []string `json:"ipScope" gorm:"-"` // ip范围
IpScopeStr string `json:"-" gorm:"ipScope"`
ListenPort int `json:"listenPort"` // 服务监听端口
PrivateKey string `json:"privateKey"` // 私钥
PublicKey string `json:"publicKey"` // 公钥
PostUpScript string `json:"postUpScript"`
PreDownScript string `json:"preDownScript"`
PostDownScript string `json:"postDownScript"`
}

View File

@ -2,9 +2,12 @@ package repository
import (
"encoding/json"
"errors"
"gitee.ltd/lxh/logger/log"
"github.com/spf13/cast"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"gorm.io/gorm"
"strings"
"wireguard-dashboard/client"
"wireguard-dashboard/http/param"
"wireguard-dashboard/model/entity"
@ -32,9 +35,9 @@ func Client() clientRepo {
// @return err
func (r clientRepo) List(p param.ClientList) (data []vo.Client, total int64, err error) {
err = r.Table("t_wg_client as twc").Scopes(utils.Page(p.Current, p.Size)).Joins("LEFT JOIN t_user as tu ON twc.user_id = tu.id").
Select("twc.id", "twc.created_at", "twc.updated_at", "twc.name", "twc.email", "twc.subnet_range", "twc.ip_allocation", "twc.allowed_ips",
"twc.extra_allowed_ips", "twc.endpoint", "twc.use_server_dns", "twc.enable_after_creation", "twc.enabled", "twc.keys as keys_str", "tu.name as create_user").
Find(&data).Offset(-1).Limit(-1).Count(&total).Error
Select("twc.id", "twc.created_at", "twc.updated_at", "twc.name", "twc.email", "twc.subnet_range", "twc.ip_allocation as ip_allocation_str", "twc.allowed_ips as allowed_ips_str",
"twc.extra_allowed_ips as extra_allowed_ips_str", "twc.endpoint", "twc.use_server_dns", "twc.enable_after_creation", "twc.enabled", "twc.keys as keys_str", "tu.name as create_user").
Order("twc.created_at DESC").Find(&data).Offset(-1).Limit(-1).Count(&total).Error
if err != nil {
return
@ -44,6 +47,15 @@ func (r clientRepo) List(p param.ClientList) (data []vo.Client, total int64, err
if v.KeysStr != "" {
_ = json.Unmarshal([]byte(v.KeysStr), &data[i].Keys)
}
if v.IpAllocationStr != "" {
data[i].IpAllocation = strings.Split(v.IpAllocationStr, ",")
}
if v.AllowedIpsStr != "" {
data[i].AllowedIps = strings.Split(v.AllowedIpsStr, ",")
}
if v.ExtraAllowedIpsStr != "" {
data[i].ExtraAllowedIps = strings.Split(v.ExtraAllowedIpsStr, ",")
}
}
return
@ -65,9 +77,9 @@ func (r clientRepo) Save(p param.SaveClient, adminId string) (client *entity.Cli
Name: p.Name,
Email: p.Email,
SubnetRange: p.SubnetRange,
IpAllocation: p.IpAllocation,
AllowedIps: p.AllowedIPS,
ExtraAllowedIps: p.ExtraAllowedIPS,
IpAllocation: strings.Join(p.IpAllocation, ","),
AllowedIps: strings.Join(p.AllowedIPS, ","),
ExtraAllowedIps: strings.Join(p.ExtraAllowedIPS, ","),
Endpoint: p.Endpoint,
UseServerDns: p.UseServerDNS,
EnableAfterCreation: p.EnabledAfterCreation,
@ -85,6 +97,17 @@ func (r clientRepo) Save(p param.SaveClient, adminId string) (client *entity.Cli
return
}
// 查询新增的ip地址是否已经存在了
var count int64
if err = r.Model(&entity.Client{}).Where("ip_allocation in (?)", p.IpAllocation).Count(&count).Error; err != nil {
log.Errorf("查询IP地址是否存在失败: %v", err.Error())
return
}
if count > 0 {
return nil, errors.New("该客户端的IP已经存在请检查后再添加")
}
// 为空,新增
privateKey, err := wgtypes.GeneratePrivateKey()
if err != nil {
@ -107,9 +130,9 @@ func (r clientRepo) Save(p param.SaveClient, adminId string) (client *entity.Cli
Name: p.Name,
Email: p.Email,
SubnetRange: p.SubnetRange,
IpAllocation: p.IpAllocation,
AllowedIps: p.AllowedIPS,
ExtraAllowedIps: p.ExtraAllowedIPS,
IpAllocation: strings.Join(p.IpAllocation, ","),
AllowedIps: strings.Join(p.AllowedIPS, ","),
ExtraAllowedIps: strings.Join(p.ExtraAllowedIPS, ","),
Endpoint: p.Endpoint,
UseServerDns: p.UseServerDNS,
EnableAfterCreation: p.EnabledAfterCreation,
@ -121,3 +144,26 @@ func (r clientRepo) Save(p param.SaveClient, adminId string) (client *entity.Cli
err = r.Model(&entity.Client{}).Create(ent).Error
return
}
// Delete
// @description: 删除客户端
// @receiver r
// @param id
// @return err
func (r clientRepo) Delete(id string) (err error) {
return r.Model(&entity.Client{}).Where("id = ?", id).Delete(&entity.Client{}).Error
}
// GetById
// @description: 根据id获取客户端详情
// @receiver r
// @param id
// @return data
// @return err
func (r clientRepo) GetById(id string) (data entity.Client, err error) {
err = r.Model(&entity.Client{}).Where("id = ?", id).Preload("Server").First(&data).Error
if err != nil {
return
}
return
}

View File

@ -24,7 +24,7 @@ func Server() server {
// @return data
// @return err
func (r server) GetServer() (data *vo.Server, err error) {
err = r.Model(&entity.Server{}).First(&data).Error
err = r.Model(&entity.Server{}).Select("id", "ip_scope as ip_scope_str", "listen_port", "private_key", "public_key", "post_up_script", "pre_down_script", "post_down_script").First(&data).Error
return
}

View File

@ -9,7 +9,10 @@ import (
func ClientApi(r *gin.RouterGroup) {
apiGroup := r.Group("client", middleware.Authorization())
{
apiGroup.GET("list", api.Client().List) // 客户端列表
apiGroup.POST("save", api.Client().Save) // 新增/编辑客户端
apiGroup.GET("list", api.Client().List) // 客户端列表
apiGroup.POST("save", api.Client().Save) // 新增/编辑客户端
apiGroup.DELETE(":id", api.Client().Delete) // 删除客户端
apiGroup.POST("download/:id", api.Client().Download) // 下载客户端配置文件
apiGroup.POST("generate-qrcode/:id", api.Client().GenerateQrCode) // 生成客户端二维码
}
}

View File

@ -9,8 +9,7 @@ import (
func ServerApi(r *gin.RouterGroup) {
apiGroup := r.Group("server", middleware.Authorization())
{
apiGroup.GET("", api.Server().GetServer) // 获取服务端信息
apiGroup.GET("global-setting", api.Server().GetGlobalSetting) // 获取服务端全局配置
apiGroup.POST("", api.Server().SaveServer) // 新增/更新服务端信息
apiGroup.GET("", api.Server().GetServer) // 获取服务端信息
apiGroup.POST("", api.Server().SaveServer) // 新增/更新服务端信息
}
}

18
route/setting.go Normal file
View File

@ -0,0 +1,18 @@
package route
import (
"github.com/gin-gonic/gin"
"wireguard-dashboard/http/api"
"wireguard-dashboard/middleware"
)
// SettingApi
// @description: 设置相关API
// @param r
func SettingApi(r *gin.RouterGroup) {
apiGroup := r.Group("setting", middleware.Authorization())
{
apiGroup.GET("server", api.Setting().GetGlobalSetting) // 获取全局服务端配置
apiGroup.GET("public-ip", api.Setting().GetPublicNetworkIP) // 获取公网IP
}
}

View File

@ -106,7 +106,7 @@ func (s Script) InitServer() error {
// 初始化服务端的全局配置
var data = map[string]any{
"endpointAddress": utils.Network().GetHostPublicIP(),
"dnsServer": "10.10.10.1/24",
"dnsServer": []string{"10.10.10.1/24"},
"MTU": 1450,
"persistentKeepalive": 15,
"firewallMark": "",

View File

@ -1,6 +1,7 @@
[Interface]
PrivateKey = {{ .PrivateKey|html }}
Address = {{ .IpAllocation|html }}
{{ if .DNS }}DNS = {{ .DNS|html }} {{ end }}
MTU = {{ .MTU }}
[Peer]

38
utils/qr_code.go Normal file
View File

@ -0,0 +1,38 @@
package utils
import (
"encoding/base64"
"gitee.ltd/lxh/logger/log"
"github.com/skip2/go-qrcode"
)
type qrCode struct{}
func QRCode() qrCode {
return qrCode{}
}
// GenerateQrCodeBase64
// @description: 生成二维码
// @receiver qr
// @param content
// @param size
// @return imgStr
// @return err
func (qr qrCode) GenerateQrCodeBase64(content []byte, size int) (imgStr string, err error) {
q, err := qrcode.New(string(content), qrcode.Highest)
if err != nil {
log.Errorf("初始化二维码对象失败: %v", err.Error())
return
}
q.DisableBorder = false
png, err := q.PNG(size)
if err != nil {
log.Errorf("生成二维码失败: %v", err.Error())
return "", err
}
imgStr = "data:image/png;base64," + base64.StdEncoding.EncodeToString(png)
return
}

View File

@ -24,7 +24,7 @@ func (templateUtils) Parse(filepath string) (parseTemplate *template.Template, e
return
}
parseTemplate, err = template.New("wg0.conf").Parse(string(file))
parseTemplate, err = template.New("wg.conf").Parse(string(file))
return
}