Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3e112cb672 | ||
|
1950150f42 | ||
|
d7680317c3 | ||
|
0964384b52 | ||
|
cbe1188e51 | ||
|
1bcad97ed2 | ||
|
c2a9618f27 | ||
|
8dab976cba | ||
|
a424a5e0b3 | ||
|
073bcc4a1d | ||
|
5df6ccefe2 | ||
|
6f249d20b0 | ||
|
67f394f136 | ||
|
d1bb49c208 | ||
|
92f5f26ad5 | ||
|
97e6e80d5a | ||
|
0d28bd3445 | ||
|
c1d81b9af5 | ||
|
36951a5bb8 | ||
|
911bc95b16 | ||
|
b1b49e2605 |
@ -3,6 +3,7 @@ package component
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"wireguard-dashboard/client"
|
"wireguard-dashboard/client"
|
||||||
@ -49,8 +50,8 @@ func (CaptchaStore) Get(id string, clear bool) string {
|
|||||||
// @param clear
|
// @param clear
|
||||||
// @return bool
|
// @return bool
|
||||||
func (c CaptchaStore) Verify(id, answer string, clear bool) bool {
|
func (c CaptchaStore) Verify(id, answer string, clear bool) bool {
|
||||||
//if os.Getenv("GIN_MODE") != "release" {
|
if os.Getenv("GIN_MODE") != "release" {
|
||||||
// return true
|
return true
|
||||||
//}
|
}
|
||||||
return strings.ToUpper(answer) == strings.ToUpper(c.Get(id, clear))
|
return strings.ToUpper(answer) == strings.ToUpper(c.Get(id, clear))
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,19 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"gitee.ltd/lxh/logger/log"
|
"gitee.ltd/lxh/logger/log"
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
"github.com/google/uuid"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"wireguard-dashboard/client"
|
"wireguard-dashboard/client"
|
||||||
|
"wireguard-dashboard/config"
|
||||||
"wireguard-dashboard/constant"
|
"wireguard-dashboard/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Secret = "IK8MSs76Pb2VJxleTDadf1Wzu3h9QROLv0XtmnCUErYgBG5wAyjk4cioqFZHNpZG"
|
const Secret = "IK8MSs76Pb2VJxleTDadf1Wzu3h9QROLv0XtmnCUErYgBG5wAyjk4cioqFZHNpZG"
|
||||||
|
|
||||||
type JwtClaims struct {
|
type JwtClaims struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
jwt.RegisteredClaims `json:"-"`
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func JWT() JwtClaims {
|
func JWT() JwtClaims {
|
||||||
@ -36,10 +38,12 @@ func (j JwtClaims) GenerateToken(userId string) (token string, expireTime *jwt.N
|
|||||||
claims := JwtClaims{
|
claims := JwtClaims{
|
||||||
ID: userId,
|
ID: userId,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
Subject: "wireguard-dashboard",
|
Issuer: config.Config.Http.Endpoint, // 颁发站点
|
||||||
|
Subject: "wg-dashboard",
|
||||||
ExpiresAt: expireTime,
|
ExpiresAt: expireTime,
|
||||||
NotBefore: notBefore,
|
NotBefore: notBefore,
|
||||||
IssuedAt: issuedAt,
|
IssuedAt: issuedAt,
|
||||||
|
ID: uuid.NewString(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,6 @@ type config struct {
|
|||||||
Database *database `yaml:"database"`
|
Database *database `yaml:"database"`
|
||||||
Redis *redis `yaml:"redis"`
|
Redis *redis `yaml:"redis"`
|
||||||
File *file `yaml:"file"`
|
File *file `yaml:"file"`
|
||||||
Mail *mail `yaml:"mail"`
|
Mail *mail `yaml:"email"`
|
||||||
Wireguard *wireguard `yaml:"wireguard"`
|
Wireguard *wireguard `yaml:"wireguard"`
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
type http struct {
|
type http struct {
|
||||||
Port uint `yaml:"port"`
|
Port uint `yaml:"port"`
|
||||||
|
Endpoint string `yaml:"endpoint"`
|
||||||
}
|
}
|
||||||
|
17
cron_task/cron.go
Normal file
17
cron_task/cron.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package cron_task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitee.ltd/lxh/logger/log"
|
||||||
|
"github.com/go-co-op/gocron/v2"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartCronTask() {
|
||||||
|
s, err := gocron.NewScheduler()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("初始化定时任务失败: %v", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _ = s.NewJob(gocron.DurationJob(time.Hour), gocron.NewTask(offlineMonitoring)) // 每小时执行一次
|
||||||
|
s.Start()
|
||||||
|
}
|
63
cron_task/offline_monitoring.go
Normal file
63
cron_task/offline_monitoring.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package cron_task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gitee.ltd/lxh/logger/log"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"wireguard-dashboard/client"
|
||||||
|
"wireguard-dashboard/repository"
|
||||||
|
"wireguard-dashboard/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// offlineMonitoring
|
||||||
|
// @description: 离线监听任务
|
||||||
|
func offlineMonitoring() {
|
||||||
|
devices, err := client.WireguardClient.Devices()
|
||||||
|
if err != nil {
|
||||||
|
time.Sleep(5 * time.Minute) // 休眠五分钟再执行
|
||||||
|
offlineMonitoring()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历客户端数据,并渲染数据信息
|
||||||
|
for _, d := range devices {
|
||||||
|
for _, p := range d.Peers {
|
||||||
|
var ipAllocation string
|
||||||
|
for _, iaip := range p.AllowedIPs {
|
||||||
|
ipAllocation += iaip.String() + ","
|
||||||
|
}
|
||||||
|
ipAllocation = strings.TrimRight(ipAllocation, ",")
|
||||||
|
isOnline := time.Since(p.LastHandshakeTime).Minutes() < 3
|
||||||
|
|
||||||
|
// 未离线
|
||||||
|
if isOnline {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
clientInfo, err := repository.Client().GetByPublicKey(p.PublicKey.String())
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 没有启用离线监听时,即使客户端已经离线则也不执行
|
||||||
|
if clientInfo.OfflineMonitoring == nil || *clientInfo.OfflineMonitoring != 1 || clientInfo.Email == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
content := fmt.Sprintf("客户端:%s\r\n", clientInfo.Name)
|
||||||
|
content += fmt.Sprintf("客户端IP:%s\r\n", ipAllocation)
|
||||||
|
content += fmt.Sprintf("端点IP:%s\r\n", p.Endpoint.String())
|
||||||
|
content += fmt.Sprintf("最后握手时间:%s\r\n", p.LastHandshakeTime.Format("2006-01-02 15:04:05"))
|
||||||
|
|
||||||
|
// 离线并且配置了邮箱,准备发送邮件
|
||||||
|
err = utils.Mail().SendMail(clientInfo.Email, fmt.Sprintf("客户端[%s]离线通知", clientInfo.Name), content, "")
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("发送离线通知邮件失败: %v", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
go.mod
43
go.mod
@ -8,17 +8,19 @@ require (
|
|||||||
github.com/dustin/go-humanize v1.0.1
|
github.com/dustin/go-humanize v1.0.1
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/glebarez/sqlite v1.11.0
|
github.com/glebarez/sqlite v1.11.0
|
||||||
|
github.com/go-co-op/gocron/v2 v2.5.0
|
||||||
github.com/go-resty/resty/v2 v2.11.0
|
github.com/go-resty/resty/v2 v2.11.0
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
|
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
|
||||||
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/mojocn/base64Captcha v1.3.6
|
github.com/mojocn/base64Captcha v1.3.6
|
||||||
github.com/redis/go-redis/v9 v9.5.1
|
github.com/redis/go-redis/v9 v9.5.1
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
github.com/spf13/cast v1.6.0
|
github.com/spf13/cast v1.6.0
|
||||||
golang.org/x/crypto v0.21.0
|
golang.org/x/crypto v0.22.0
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
gopkg.in/fsnotify.v1 v1.4.7
|
gopkg.in/fsnotify.v1 v1.4.7
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gorm.io/driver/mysql v1.5.4
|
gorm.io/driver/mysql v1.5.4
|
||||||
gorm.io/driver/postgres v1.5.6
|
gorm.io/driver/postgres v1.5.6
|
||||||
@ -28,13 +30,17 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible // indirect
|
github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bytedance/sonic v1.9.1 // indirect
|
github.com/bytedance/sonic v1.11.6 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
github.com/caarlos0/env/v6 v6.10.1 // indirect
|
github.com/caarlos0/env/v6 v6.10.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
|
github.com/gin-contrib/pprof v1.5.0 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||||
github.com/go-kit/kit v0.12.0 // indirect
|
github.com/go-kit/kit v0.12.0 // indirect
|
||||||
@ -42,7 +48,7 @@ require (
|
|||||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
@ -56,13 +62,13 @@ require (
|
|||||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/jpillora/backoff v1.0.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.7 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
|
||||||
github.com/lixh00/loki-client-go v1.0.1 // indirect
|
github.com/lixh00/loki-client-go v1.0.1 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
|
||||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||||
@ -72,7 +78,7 @@ require (
|
|||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
||||||
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
|
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/prometheus/client_golang v1.13.0 // indirect
|
github.com/prometheus/client_golang v1.13.0 // indirect
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
@ -80,26 +86,27 @@ require (
|
|||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
github.com/prometheus/prometheus v1.8.2-0.20201028100903-3245b3267b24 // indirect
|
github.com/prometheus/prometheus v1.8.2-0.20201028100903-3245b3267b24 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/multierr v1.10.0 // indirect
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
|
||||||
golang.org/x/image v0.15.0 // indirect
|
golang.org/x/image v0.15.0 // indirect
|
||||||
golang.org/x/net v0.21.0 // indirect
|
golang.org/x/net v0.24.0 // indirect
|
||||||
golang.org/x/oauth2 v0.1.0 // indirect
|
golang.org/x/oauth2 v0.1.0 // indirect
|
||||||
golang.org/x/sync v0.1.0 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/sys v0.18.0 // indirect
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.15.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b // indirect
|
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 // indirect
|
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 // indirect
|
||||||
google.golang.org/grpc v1.50.1 // indirect
|
google.golang.org/grpc v1.50.1 // indirect
|
||||||
google.golang.org/protobuf v1.33.0 // indirect
|
google.golang.org/protobuf v1.34.0 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
modernc.org/libc v1.22.5 // indirect
|
modernc.org/libc v1.22.5 // indirect
|
||||||
modernc.org/mathutil v1.5.0 // indirect
|
modernc.org/mathutil v1.5.0 // indirect
|
||||||
|
60
go.sum
60
go.sum
@ -123,6 +123,10 @@ github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0
|
|||||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||||
|
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||||
|
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
|
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
|
||||||
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
|
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
|
||||||
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
|
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
|
||||||
@ -145,6 +149,10 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D
|
|||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||||
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
|
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||||
|
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||||
@ -203,8 +211,12 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
|
|||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/gin-contrib/pprof v1.5.0 h1:E/Oy7g+kNw94KfdCy3bZxQFtyDnAX2V7axRS7sNYVrU=
|
||||||
|
github.com/gin-contrib/pprof v1.5.0/go.mod h1:GqFL6LerKoCQ/RSWnkYczkTJ+tOAUVN/8sbnEtaqOKs=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||||
@ -217,6 +229,8 @@ github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0
|
|||||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||||
|
github.com/go-co-op/gocron/v2 v2.5.0 h1:ff/TJX9GdTJBDL1il9cyd/Sj3WnS+BB7ZzwHKSNL5p8=
|
||||||
|
github.com/go-co-op/gocron/v2 v2.5.0/go.mod h1:ckPQw96ZuZLRUGu88vVpd9a6d9HakI14KWahFZtGvNw=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
@ -302,6 +316,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
|
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
|
||||||
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
|
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
@ -498,6 +514,10 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW
|
|||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
|
||||||
|
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
|
||||||
|
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
||||||
|
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||||
@ -530,8 +550,11 @@ github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM52
|
|||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
||||||
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
@ -549,6 +572,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||||
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||||
@ -575,6 +600,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
|
|||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
@ -668,6 +695,8 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP
|
|||||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||||
@ -735,6 +764,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qq
|
|||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
|
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
|
||||||
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
|
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
@ -786,6 +817,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
@ -797,8 +829,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
|
||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
@ -809,6 +843,8 @@ github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW
|
|||||||
github.com/uber/jaeger-lib v2.4.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
github.com/uber/jaeger-lib v2.4.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
||||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
@ -858,6 +894,8 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
|||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||||
|
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
@ -879,6 +917,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@ -892,6 +932,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
|
||||||
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
@ -969,6 +1011,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -992,8 +1036,9 @@ golang.org/x/sync v0.0.0-20200930132711-30421366ff76/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -1068,6 +1113,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
@ -1085,6 +1132,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||||
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -1272,9 +1321,9 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
|||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
|
google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4=
|
||||||
|
google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@ -1286,8 +1335,6 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
|||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
|
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
|
||||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
@ -1342,6 +1389,7 @@ modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
|||||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||||
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
|
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
|
||||||
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||||
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
@ -202,49 +202,15 @@ func (clients) Download(c *gin.Context) {
|
|||||||
var keys template_data.Keys
|
var keys template_data.Keys
|
||||||
_ = json.Unmarshal([]byte(data.Keys), &keys)
|
_ = json.Unmarshal([]byte(data.Keys), &keys)
|
||||||
|
|
||||||
setting, err := repository.System().GetServerSetting()
|
serverSetting, err := repository.System().GetServerSetting()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GinResponse(c).FailedWithMsg("获取设置失败")
|
utils.GinResponse(c).FailedWithMsg("获取设置失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverDNS []string
|
outPath, err := utils.Wireguard().GenerateClientFile(&data, serverSetting)
|
||||||
if *data.UseServerDns == 1 {
|
|
||||||
serverDNS = setting.DnsServer
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理一下数据
|
|
||||||
execData := template_data.ClientConfig{
|
|
||||||
PrivateKey: keys.PrivateKey,
|
|
||||||
IpAllocation: data.IpAllocation,
|
|
||||||
MTU: setting.MTU,
|
|
||||||
DNS: strings.Join(serverDNS, ","),
|
|
||||||
PublicKey: data.Server.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 {
|
if err != nil {
|
||||||
utils.GinResponse(c).FailedWithMsg("读取模板文件失败")
|
utils.GinResponse(c).FailedWithErr("生成失败", err)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = utils.Template().Execute(parseTemplate, execData, outPath)
|
|
||||||
if err != nil {
|
|
||||||
utils.GinResponse(c).FailedWithMsg("文件渲染失败")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,49 +245,15 @@ func (clients) GenerateQrCode(c *gin.Context) {
|
|||||||
var keys template_data.Keys
|
var keys template_data.Keys
|
||||||
_ = json.Unmarshal([]byte(data.Keys), &keys)
|
_ = json.Unmarshal([]byte(data.Keys), &keys)
|
||||||
|
|
||||||
setting, err := repository.System().GetServerSetting()
|
serverSetting, err := repository.System().GetServerSetting()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GinResponse(c).FailedWithMsg("获取设置失败")
|
utils.GinResponse(c).FailedWithMsg("获取设置失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverDNS []string
|
outPath, err := utils.Wireguard().GenerateClientFile(&data, serverSetting)
|
||||||
if *data.UseServerDns == 1 {
|
|
||||||
serverDNS = setting.DnsServer
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理一下数据
|
|
||||||
execData := template_data.ClientConfig{
|
|
||||||
PrivateKey: keys.PrivateKey,
|
|
||||||
IpAllocation: data.IpAllocation,
|
|
||||||
MTU: setting.MTU,
|
|
||||||
DNS: strings.Join(serverDNS, ","),
|
|
||||||
PublicKey: data.Server.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 {
|
if err != nil {
|
||||||
utils.GinResponse(c).FailedWithMsg("读取模板文件失败")
|
utils.GinResponse(c).FailedWithErr("生成失败", err)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = utils.Template().Execute(parseTemplate, execData, outPath)
|
|
||||||
if err != nil {
|
|
||||||
utils.GinResponse(c).FailedWithMsg("文件渲染失败")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +279,59 @@ func (clients) GenerateQrCode(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendEmail
|
||||||
|
// @description: 发送邮件
|
||||||
|
// @receiver clients
|
||||||
|
// @param c
|
||||||
|
func (clients) SendEmail(c *gin.Context) {
|
||||||
|
var id = c.Param("id")
|
||||||
|
if id == "" || id == "undefined" {
|
||||||
|
utils.GinResponse(c).FailedWithMsg("id不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先校验一下邮箱发送是否可用
|
||||||
|
if err := utils.Mail().VerifyConfig(); err != nil {
|
||||||
|
utils.GinResponse(c).FailedWithMsg(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取该客户端信息
|
||||||
|
clientInfo, err := repository.Client().GetById(id)
|
||||||
|
if err != nil {
|
||||||
|
utils.GinResponse(c).FailedWithErr("获取失败", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if clientInfo.Email == "" {
|
||||||
|
utils.GinResponse(c).FailedWithMsg("当前客户端未配置联系邮箱!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serverSetting, err := repository.System().GetServerSetting()
|
||||||
|
if err != nil {
|
||||||
|
utils.GinResponse(c).FailedWithMsg("获取设置失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
outPath, err := utils.Wireguard().GenerateClientFile(&clientInfo, serverSetting)
|
||||||
|
if err != nil {
|
||||||
|
utils.GinResponse(c).FailedWithErr("生成失败", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = utils.Mail().SendMail(clientInfo.Email, fmt.Sprintf("客户端: %s", clientInfo.Name), "请查收附件", outPath)
|
||||||
|
if err != nil {
|
||||||
|
utils.GinResponse(c).FailedWithErr("发送邮件失败", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = os.Remove(outPath); err != nil {
|
||||||
|
log.Errorf("删除临时文件失败: %s", err.Error())
|
||||||
|
}
|
||||||
|
utils.GinResponse(c).OK()
|
||||||
|
}
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
// @description: 获取客户端状态信息,链接状态等
|
// @description: 获取客户端状态信息,链接状态等
|
||||||
// @receiver clients
|
// @receiver clients
|
||||||
@ -373,7 +358,7 @@ func (clients) Status(c *gin.Context) {
|
|||||||
ipAllocation += iaip.String() + ","
|
ipAllocation += iaip.String() + ","
|
||||||
}
|
}
|
||||||
ipAllocation = strings.TrimRight(ipAllocation, ",")
|
ipAllocation = strings.TrimRight(ipAllocation, ",")
|
||||||
isOnline := time.Since(p.LastHandshakeTime).Minutes() < 1
|
isOnline := time.Since(p.LastHandshakeTime).Minutes() < 3
|
||||||
data = append(data, vo.ClientStatus{
|
data = append(data, vo.ClientStatus{
|
||||||
ID: clientInfo.Id,
|
ID: clientInfo.Id,
|
||||||
Name: clientInfo.Name,
|
Name: clientInfo.Name,
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
"gitee.ltd/lxh/logger/log"
|
"gitee.ltd/lxh/logger/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"strings"
|
||||||
"wireguard-dashboard/client"
|
"wireguard-dashboard/client"
|
||||||
"wireguard-dashboard/component"
|
"wireguard-dashboard/component"
|
||||||
"wireguard-dashboard/constant"
|
"wireguard-dashboard/constant"
|
||||||
@ -157,6 +160,30 @@ func (user) Save(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 只有修改才有头像值
|
||||||
|
if p.Avatar != "" && p.ID != "" {
|
||||||
|
// 判断头像是base64开头的就需要重新上传更新
|
||||||
|
if strings.HasPrefix(p.Avatar, "data:image/png;base64,") {
|
||||||
|
avatar := strings.Replace(p.Avatar, "data:image/png;base64,", "", -1)
|
||||||
|
avatarByte, err := base64.StdEncoding.DecodeString(avatar)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("反解析头像失败: %v", err.Error())
|
||||||
|
utils.GinResponse(c).FailedWithMsg("上传头像失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := utils.FileSystem().UploadFile(avatarByte, ".png")
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("上传头像失败: %v", err.Error())
|
||||||
|
utils.GinResponse(c).FailedWithMsg("上传头像失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Avatar = file
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if err := repository.User().Save(&entity.User{
|
if err := repository.User().Save(&entity.User{
|
||||||
Base: entity.Base{
|
Base: entity.Base{
|
||||||
Id: p.ID,
|
Id: p.ID,
|
||||||
@ -250,3 +277,17 @@ func (user) DeleteUser(c *gin.Context) {
|
|||||||
|
|
||||||
utils.GinResponse(c).OK()
|
utils.GinResponse(c).OK()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChangeAvatar
|
||||||
|
// @description: 切换头像
|
||||||
|
// @receiver user
|
||||||
|
// @param c
|
||||||
|
func (user) ChangeAvatar(c *gin.Context) {
|
||||||
|
avatar, err := utils.Avatar().GenerateAvatar(false)
|
||||||
|
if err != nil {
|
||||||
|
utils.GinResponse(c).FailedWithErr("生成头像失败", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.GinResponse(c).OKWithData(fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString([]byte(avatar))))
|
||||||
|
}
|
||||||
|
@ -35,6 +35,7 @@ type SaveClient struct {
|
|||||||
EnabledAfterCreation *int `json:"enableAfterCreation" form:"enableAfterCreation" binding:"required,oneof=1 0"`
|
EnabledAfterCreation *int `json:"enableAfterCreation" form:"enableAfterCreation" binding:"required,oneof=1 0"`
|
||||||
Keys *template_data.Keys `json:"keys" form:"keys" binding:"omitempty"`
|
Keys *template_data.Keys `json:"keys" form:"keys" binding:"omitempty"`
|
||||||
Enabled *int `json:"enabled" form:"enabled" binding:"required,oneof=1 0"`
|
Enabled *int `json:"enabled" form:"enabled" binding:"required,oneof=1 0"`
|
||||||
|
OfflineMonitoring *int `json:"offlineMonitoring" form:"offlineMonitoring" binding:"required,oneof=1 0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControlServer
|
// ControlServer
|
||||||
|
@ -12,8 +12,10 @@ import (
|
|||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
gl "gorm.io/gorm/logger"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
"wireguard-dashboard/client"
|
"wireguard-dashboard/client"
|
||||||
"wireguard-dashboard/config"
|
"wireguard-dashboard/config"
|
||||||
)
|
)
|
||||||
@ -69,8 +71,18 @@ func initDatabase() {
|
|||||||
dbDialector = sqlite.Open(config.Config.Database.GetDSN())
|
dbDialector = sqlite.Open(config.Config.Database.GetDSN())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logLevel := gl.Info
|
||||||
|
//if os.Getenv("GIN_MODE") == "release" {
|
||||||
|
// logLevel = gl.Error
|
||||||
|
//}
|
||||||
|
|
||||||
db, err := gorm.Open(dbDialector, &gorm.Config{
|
db, err := gorm.Open(dbDialector, &gorm.Config{
|
||||||
Logger: logger.DefaultGormLogger(),
|
Logger: logger.NewGormLoggerWithConfig(gl.Config{
|
||||||
|
SlowThreshold: time.Second, // Slow SQL threshold
|
||||||
|
IgnoreRecordNotFoundError: false, // 忽略没找到结果的错误
|
||||||
|
LogLevel: logLevel, // Log level
|
||||||
|
Colorful: false, // Disable color
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
7
main.go
7
main.go
@ -3,10 +3,12 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"gitee.ltd/lxh/logger/log"
|
"gitee.ltd/lxh/logger/log"
|
||||||
|
"github.com/gin-contrib/pprof"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
"wireguard-dashboard/config"
|
"wireguard-dashboard/config"
|
||||||
|
"wireguard-dashboard/cron_task"
|
||||||
"wireguard-dashboard/initialize"
|
"wireguard-dashboard/initialize"
|
||||||
"wireguard-dashboard/queues"
|
"wireguard-dashboard/queues"
|
||||||
"wireguard-dashboard/route"
|
"wireguard-dashboard/route"
|
||||||
@ -18,7 +20,8 @@ func init() {
|
|||||||
if err := script.NewScript().Do(); err != nil {
|
if err := script.NewScript().Do(); err != nil {
|
||||||
log.Errorf("执行脚本失败: %v", err.Error())
|
log.Errorf("执行脚本失败: %v", err.Error())
|
||||||
}
|
}
|
||||||
go queues.StartConsumer() // 启动队列
|
go queues.StartConsumer() // 启动队列
|
||||||
|
go cron_task.StartCronTask() // 启动定时任务
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -33,6 +36,8 @@ func main() {
|
|||||||
)
|
)
|
||||||
handler := route.InitRouter()
|
handler := route.InitRouter()
|
||||||
|
|
||||||
|
pprof.Register(handler)
|
||||||
|
|
||||||
httpServe := http.Server{
|
httpServe := http.Server{
|
||||||
Addr: fmt.Sprintf(":%d", config.Config.Http.Port),
|
Addr: fmt.Sprintf(":%d", config.Config.Http.Port),
|
||||||
Handler: handler,
|
Handler: handler,
|
||||||
|
@ -28,6 +28,13 @@ func Authorization() gin.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果token的颁发者与请求的站点不一致,则直接给它狗日的丢出去
|
||||||
|
if userClaims.Issuer != utils.GetHost(c.Request.Header.Get("Referer")) {
|
||||||
|
utils.GinResponse(c).AuthorizationFailed()
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 查询用户
|
// 查询用户
|
||||||
user, err := repository.User().GetUserById(userClaims.ID)
|
user, err := repository.User().GetUserById(userClaims.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -35,6 +35,7 @@ type Client struct {
|
|||||||
Keys string `json:"keys" gorm:"type:text;default null;comment:'公钥和密钥的json串'"`
|
Keys string `json:"keys" gorm:"type:text;default null;comment:'公钥和密钥的json串'"`
|
||||||
UserId string `json:"userId" gorm:"type:char(36);not null;comment:'创建人id'"`
|
UserId string `json:"userId" gorm:"type:char(36);not null;comment:'创建人id'"`
|
||||||
Enabled *int `json:"enabled" gorm:"type:tinyint(1);default 1;comment:'状态(0 - 禁用 | 1 - 正常)'"`
|
Enabled *int `json:"enabled" gorm:"type:tinyint(1);default 1;comment:'状态(0 - 禁用 | 1 - 正常)'"`
|
||||||
|
OfflineMonitoring *int `json:"offlineMonitoring" gorm:"tinyint(1);default 0;comment:'是否启用离线监听(0 - 禁用 | 1 - 启用)"`
|
||||||
User *User `json:"user" gorm:"foreignKey:UserId"`
|
User *User `json:"user" gorm:"foreignKey:UserId"`
|
||||||
Server *Server `json:"server" gorm:"foreignKey:ServerId"`
|
Server *Server `json:"server" gorm:"foreignKey:ServerId"`
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ type Client struct {
|
|||||||
Keys template_data.Keys `json:"keys" gorm:"-"`
|
Keys template_data.Keys `json:"keys" gorm:"-"`
|
||||||
CreateUser string `json:"createUser"`
|
CreateUser string `json:"createUser"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
|
OfflineMonitoring int `json:"offlineMonitoring"`
|
||||||
CreatedAt entity.JsonTime `json:"createdAt"`
|
CreatedAt entity.JsonTime `json:"createdAt"`
|
||||||
UpdatedAt entity.JsonTime `json:"updatedAt"`
|
UpdatedAt entity.JsonTime `json:"updatedAt"`
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ func asyncWireguardConfigFile() {
|
|||||||
for {
|
for {
|
||||||
result, err := client.Redis.BRPop(context.Background(), 0, fmt.Sprintf("%s", constant.SyncWgConfigFile)).Result()
|
result, err := client.Redis.BRPop(context.Background(), 0, fmt.Sprintf("%s", constant.SyncWgConfigFile)).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Errorf("获取任务失败")
|
log.Errorf("获取任务失败")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ func asyncWireguardConfigFile() {
|
|||||||
var renderClients []template_data.Client
|
var renderClients []template_data.Client
|
||||||
for _, v := range serverEnt.Clients {
|
for _, v := range serverEnt.Clients {
|
||||||
// 如果不是确认后创建或者未启用就不写入到wireguard配置文件当中
|
// 如果不是确认后创建或者未启用就不写入到wireguard配置文件当中
|
||||||
if *v.EnableAfterCreation != 1 || *v.Enabled != 1 {
|
if *v.Enabled != 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var clientKey template_data.Keys
|
var clientKey template_data.Keys
|
||||||
|
@ -3,5 +3,8 @@ package queues
|
|||||||
// StartConsumer
|
// StartConsumer
|
||||||
// @description: 启动消费者
|
// @description: 启动消费者
|
||||||
func StartConsumer() {
|
func StartConsumer() {
|
||||||
|
// 同步配置文件
|
||||||
go asyncWireguardConfigFile()
|
go asyncWireguardConfigFile()
|
||||||
|
// 离线监听
|
||||||
|
//go offlineMonitoring()
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func (r clientRepo) List(p param.ClientList) (data []vo.Client, total int64, err
|
|||||||
Scopes(utils.Page(p.Current, p.Size)).
|
Scopes(utils.Page(p.Current, p.Size)).
|
||||||
Joins("LEFT JOIN t_user as tu ON twc.user_id = tu.id").
|
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 as ip_allocation_str", "twc.allowed_ips as allowed_ips_str",
|
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")
|
"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", "twc.offline_monitoring")
|
||||||
|
|
||||||
if p.Name != "" {
|
if p.Name != "" {
|
||||||
sel.Where("twc.name LIKE ?", "%"+p.Name+"%")
|
sel.Where("twc.name LIKE ?", "%"+p.Name+"%")
|
||||||
@ -104,6 +104,7 @@ func (r clientRepo) Save(p param.SaveClient, adminId string) (client *entity.Cli
|
|||||||
EnableAfterCreation: p.EnabledAfterCreation,
|
EnableAfterCreation: p.EnabledAfterCreation,
|
||||||
UserId: adminId,
|
UserId: adminId,
|
||||||
Enabled: p.Enabled,
|
Enabled: p.Enabled,
|
||||||
|
OfflineMonitoring: p.OfflineMonitoring,
|
||||||
}
|
}
|
||||||
|
|
||||||
// id不为空,更新信息
|
// id不为空,更新信息
|
||||||
@ -113,7 +114,7 @@ func (r clientRepo) Save(p param.SaveClient, adminId string) (client *entity.Cli
|
|||||||
if err = r.Model(&entity.Client{}).
|
if err = r.Model(&entity.Client{}).
|
||||||
Where("id = ?", p.Id).Select("name", "email", "subnet_range", "ip_allocation",
|
Where("id = ?", p.Id).Select("name", "email", "subnet_range", "ip_allocation",
|
||||||
"allowed_ips", "extra_allowed_ips", "endpoint", "use_server_dns", "enable_after_creation",
|
"allowed_ips", "extra_allowed_ips", "endpoint", "use_server_dns", "enable_after_creation",
|
||||||
"user_id", "enabled").
|
"user_id", "enabled", "offline_monitoring").
|
||||||
Updates(ent).Error; err != nil {
|
Updates(ent).Error; err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -186,6 +187,7 @@ func (r clientRepo) Save(p param.SaveClient, adminId string) (client *entity.Cli
|
|||||||
Keys: string(keysStr),
|
Keys: string(keysStr),
|
||||||
UserId: adminId,
|
UserId: adminId,
|
||||||
Enabled: p.Enabled,
|
Enabled: p.Enabled,
|
||||||
|
OfflineMonitoring: p.OfflineMonitoring,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.Model(&entity.Client{}).Create(ent).Error
|
err = r.Model(&entity.Client{}).Create(ent).Error
|
||||||
@ -229,5 +231,5 @@ func (r clientRepo) GetByPublicKey(publicKey string) (data entity.Client, err er
|
|||||||
// @param id
|
// @param id
|
||||||
// @return err
|
// @return err
|
||||||
func (r clientRepo) Disabled(id string) (err error) {
|
func (r clientRepo) Disabled(id string) (err error) {
|
||||||
return r.Model(&entity.Client{}).Where("id = ?", id).Update("status", 0).Error
|
return r.Model(&entity.Client{}).Where("id = ?", id).Update("enabled", 0).Error
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,8 @@ func (r server) Update(p param.SaveServer) (err error) {
|
|||||||
"post_up_script": p.PostUpScript,
|
"post_up_script": p.PostUpScript,
|
||||||
"pre_down_script": p.PreDownScript,
|
"pre_down_script": p.PreDownScript,
|
||||||
"post_down_script": p.PostDownScript,
|
"post_down_script": p.PostDownScript,
|
||||||
|
"private_key": p.PrivateKey,
|
||||||
|
"public_key": p.PublicKey,
|
||||||
}
|
}
|
||||||
return r.Model(&entity.Server{}).Where("id = ?", p.Id).Updates(&update).Error
|
return r.Model(&entity.Server{}).Where("id = ?", p.Id).Updates(&update).Error
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ func (r user) Save(ent *entity.User) (err error) {
|
|||||||
|
|
||||||
// 没有头像就生成一个头像
|
// 没有头像就生成一个头像
|
||||||
if ent.Avatar == "" {
|
if ent.Avatar == "" {
|
||||||
ent.Avatar, _ = utils.Avatar().GenerateAvatar()
|
ent.Avatar, _ = utils.Avatar().GenerateAvatar(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建
|
// 创建
|
||||||
|
@ -14,6 +14,7 @@ func ClientApi(r *gin.RouterGroup) {
|
|||||||
apiGroup.DELETE(":id", middleware.Permission(), api.Client().Delete) // 删除客户端
|
apiGroup.DELETE(":id", middleware.Permission(), api.Client().Delete) // 删除客户端
|
||||||
apiGroup.POST("download/:id", api.Client().Download) // 下载客户端配置文件
|
apiGroup.POST("download/:id", api.Client().Download) // 下载客户端配置文件
|
||||||
apiGroup.POST("generate-qrcode/:id", api.Client().GenerateQrCode) // 生成客户端二维码
|
apiGroup.POST("generate-qrcode/:id", api.Client().GenerateQrCode) // 生成客户端二维码
|
||||||
|
apiGroup.POST("to-email/:id", api.Client().SendEmail) //发送邮件
|
||||||
apiGroup.GET("status", api.Client().Status) // 获取客户端链接状态监听列表
|
apiGroup.GET("status", api.Client().Status) // 获取客户端链接状态监听列表
|
||||||
apiGroup.POST("offline/:id", api.Client().Offline) // 强制下线指定客户端
|
apiGroup.POST("offline/:id", api.Client().Offline) // 强制下线指定客户端
|
||||||
apiGroup.POST("assignIP", api.Client().AssignIPAndAllowedIP) // 分配IP
|
apiGroup.POST("assignIP", api.Client().AssignIPAndAllowedIP) // 分配IP
|
||||||
|
@ -23,5 +23,6 @@ func UserApi(r *gin.RouterGroup) {
|
|||||||
userApi.GET("list", middleware.Permission(), api.UserApi().List) // 用户列表
|
userApi.GET("list", middleware.Permission(), api.UserApi().List) // 用户列表
|
||||||
userApi.PUT("change-status", middleware.Permission(), api.UserApi().ChangeUserState) // 变更状态
|
userApi.PUT("change-status", middleware.Permission(), api.UserApi().ChangeUserState) // 变更状态
|
||||||
userApi.DELETE("delete/:id", middleware.Permission(), api.UserApi().DeleteUser) // 删除用户
|
userApi.DELETE("delete/:id", middleware.Permission(), api.UserApi().DeleteUser) // 删除用户
|
||||||
|
userApi.POST("change-avatar", api.UserApi().ChangeAvatar) // 更换头像
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ func (s Script) CreateSuperAdmin() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 生成一下头像
|
// 生成一下头像
|
||||||
avatarPath, err := utils.Avatar().GenerateAvatar()
|
avatarPath, err := utils.Avatar().GenerateAvatar(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("生成头像失败: %v", err.Error())
|
log.Errorf("生成头像失败: %v", err.Error())
|
||||||
return err
|
return err
|
||||||
|
@ -19,7 +19,7 @@ func Avatar() avatar {
|
|||||||
// @receiver avatar
|
// @receiver avatar
|
||||||
// @return path
|
// @return path
|
||||||
// @return err
|
// @return err
|
||||||
func (avatar) GenerateAvatar() (path string, err error) {
|
func (avatar) GenerateAvatar(isUpload bool) (path string, err error) {
|
||||||
rand.New(rand.NewSource(time.Now().UnixNano()))
|
rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
r := client.HttpClient.R()
|
r := client.HttpClient.R()
|
||||||
result, err := r.Get(fmt.Sprintf("https://api.dicebear.com/7.x/croodles/png?seed=%d&scale=120&size=200&clip=true&randomizeIds=true&beard=variant01,variant02,variant03&"+
|
result, err := r.Get(fmt.Sprintf("https://api.dicebear.com/7.x/croodles/png?seed=%d&scale=120&size=200&clip=true&randomizeIds=true&beard=variant01,variant02,variant03&"+
|
||||||
@ -30,10 +30,13 @@ func (avatar) GenerateAvatar() (path string, err error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath, err := FileSystem().UploadFile(result.Body(), ".png")
|
if isUpload {
|
||||||
if err != nil {
|
path, err = FileSystem().UploadFile(result.Body(), ".png")
|
||||||
return "", err
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return filePath, nil
|
return string(result.Body()), nil
|
||||||
}
|
}
|
||||||
|
105
utils/mail.go
105
utils/mail.go
@ -2,77 +2,74 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"gitee.ltd/lxh/logger/log"
|
"github.com/jordan-wright/email"
|
||||||
"gopkg.in/gomail.v2"
|
|
||||||
"mime"
|
"mime"
|
||||||
|
"net/smtp"
|
||||||
|
"net/textproto"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"wireguard-dashboard/config"
|
"wireguard-dashboard/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mail struct {
|
type mail struct {
|
||||||
md *gomail.Dialer
|
*email.Email
|
||||||
|
addr string
|
||||||
|
auth smtp.Auth
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mail() mail {
|
func Mail() *mail {
|
||||||
mailDialer := gomail.NewDialer(config.Config.Mail.Host, config.Config.Mail.Port, config.Config.Mail.User, config.Config.Mail.Password)
|
var m mail
|
||||||
mailDialer.TLSConfig = &tls.Config{
|
em := email.NewEmail()
|
||||||
InsecureSkipVerify: config.Config.Mail.SkipTls,
|
m.Email = em
|
||||||
|
m.auth = smtp.PlainAuth("", config.Config.Mail.User, config.Config.Mail.Password, config.Config.Mail.Host)
|
||||||
|
m.addr = fmt.Sprintf("%s:%d", config.Config.Mail.Host, config.Config.Mail.Port)
|
||||||
|
return &m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mail) VerifyConfig() (err error) {
|
||||||
|
if m == nil {
|
||||||
|
return errors.New("邮件客户端初始化失败")
|
||||||
}
|
}
|
||||||
return mail{mailDialer}
|
|
||||||
|
if m.auth == nil || m.addr == "" {
|
||||||
|
return errors.New("邮件客户端未完成初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMail
|
// SendMail
|
||||||
// @description: 发送普通邮件
|
// @description: 发送附件
|
||||||
// @receiver mail
|
|
||||||
// @param subject
|
|
||||||
// @param toAddress
|
|
||||||
// @param content
|
|
||||||
// @return err
|
|
||||||
func (m mail) SendMail(subject, toAddress, content string) (err error) {
|
|
||||||
msg := gomail.NewMessage()
|
|
||||||
msg.SetHeader("From", msg.FormatAddress(m.md.Username, "wireguard-dashboard"))
|
|
||||||
msg.SetHeader("To", toAddress)
|
|
||||||
msg.SetHeader("Subject", subject)
|
|
||||||
msg.SetBody("text/plain", content)
|
|
||||||
|
|
||||||
if err = m.md.DialAndSend(msg); err != nil {
|
|
||||||
log.Errorf("发送普通邮件失败: %v", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendMailWithAttach
|
|
||||||
// @description: 发送并携带附件
|
|
||||||
// @receiver m
|
// @receiver m
|
||||||
|
// @param to
|
||||||
// @param subject
|
// @param subject
|
||||||
// @param toAddress
|
// @param attacheFilePath
|
||||||
// @param content
|
|
||||||
// @param attachPath
|
|
||||||
// @return err
|
// @return err
|
||||||
func (m mail) SendMailWithAttach(subject, toAddress, content, attachPath string) (err error) {
|
func (m *mail) SendMail(to, subject, content, attacheFilePath string) (err error) {
|
||||||
msg := gomail.NewMessage()
|
m.From = fmt.Sprintf("wg-dashboard <%s>", config.Config.Mail.User)
|
||||||
msg.SetHeader("From", msg.FormatAddress(m.md.Username, "wireguard-dashboard"))
|
m.To = []string{to}
|
||||||
msg.SetHeader("To", toAddress)
|
m.Subject = subject
|
||||||
msg.SetHeader("Subject", subject)
|
m.Text = []byte(content)
|
||||||
msg.SetBody("text/plain", content)
|
if attacheFilePath != "" {
|
||||||
|
atch, err := m.AttachFile(attacheFilePath)
|
||||||
rename := m.getFileName(attachPath)
|
if err != nil {
|
||||||
|
return fmt.Errorf("读取附件文件失败: %v", err.Error())
|
||||||
msg.Attach(attachPath, gomail.Rename(rename), gomail.SetHeader(map[string][]string{
|
}
|
||||||
"Content-Disposition": {
|
emHeader := textproto.MIMEHeader{}
|
||||||
fmt.Sprintf(`attachment; filename="%s"`, mime.BEncoding.Encode("UTF-8", rename)),
|
emHeader.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, mime.BEncoding.Encode("UTF-8", m.getFileName(attacheFilePath))))
|
||||||
},
|
atch.Header = emHeader
|
||||||
}))
|
|
||||||
|
|
||||||
if err = m.md.DialAndSend(msg); err != nil {
|
|
||||||
log.Errorf("发送普通邮件失败: %v", err.Error())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
if config.Config.Mail.SkipTls {
|
||||||
|
return m.Send(m.addr, m.auth)
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig := &tls.Config{}
|
||||||
|
tlsConfig.InsecureSkipVerify = config.Config.Mail.SkipTls
|
||||||
|
tlsConfig.ServerName = config.Config.Mail.Host
|
||||||
|
|
||||||
|
return m.SendWithTLS(m.addr, m.auth, tlsConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFileName
|
// getFileName
|
||||||
@ -80,6 +77,6 @@ func (m mail) SendMailWithAttach(subject, toAddress, content, attachPath string)
|
|||||||
// @receiver m
|
// @receiver m
|
||||||
// @param filePath
|
// @param filePath
|
||||||
// @return string
|
// @return string
|
||||||
func (m mail) getFileName(filePath string) string {
|
func (m *mail) getFileName(filePath string) string {
|
||||||
return filepath.Base(filePath)
|
return filepath.Base(filePath)
|
||||||
}
|
}
|
||||||
|
16
utils/url.go
Normal file
16
utils/url.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
|
// GetHost
|
||||||
|
// @description: 获取指定地址的host
|
||||||
|
// @param addr
|
||||||
|
// @return string
|
||||||
|
func GetHost(addr string) string {
|
||||||
|
uu, err := url.Parse(addr)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return uu.Host
|
||||||
|
}
|
@ -1,13 +1,19 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"wireguard-dashboard/client"
|
"wireguard-dashboard/client"
|
||||||
|
"wireguard-dashboard/model/entity"
|
||||||
|
"wireguard-dashboard/model/template_data"
|
||||||
|
"wireguard-dashboard/model/vo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wireguard struct{}
|
type wireguard struct{}
|
||||||
@ -68,6 +74,58 @@ func (w wireguard) GenerateClientIP(serverIP, rule string, assignedIPS ...string
|
|||||||
return fmt.Sprintf("%s.%s", prefix, suffix)
|
return fmt.Sprintf("%s.%s", prefix, suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateClientFile
|
||||||
|
// @description: 生成客户端临时配置文件
|
||||||
|
// @receiver w
|
||||||
|
// @param clientInfo
|
||||||
|
// @param setting
|
||||||
|
// @return tmpFilePath
|
||||||
|
// @return err
|
||||||
|
func (w wireguard) GenerateClientFile(clientInfo *entity.Client, setting *vo.ServerSetting) (tmpFilePath string, err error) {
|
||||||
|
var keys template_data.Keys
|
||||||
|
_ = json.Unmarshal([]byte(clientInfo.Keys), &keys)
|
||||||
|
|
||||||
|
var serverDNS []string
|
||||||
|
if *clientInfo.UseServerDns == 1 {
|
||||||
|
serverDNS = setting.DnsServer
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理一下数据
|
||||||
|
execData := template_data.ClientConfig{
|
||||||
|
PrivateKey: keys.PrivateKey,
|
||||||
|
IpAllocation: clientInfo.IpAllocation,
|
||||||
|
MTU: setting.MTU,
|
||||||
|
DNS: strings.Join(serverDNS, ","),
|
||||||
|
PublicKey: clientInfo.Server.PublicKey,
|
||||||
|
PresharedKey: keys.PresharedKey,
|
||||||
|
AllowedIPS: clientInfo.AllowedIps,
|
||||||
|
Endpoint: setting.EndpointAddress,
|
||||||
|
ListenPort: clientInfo.Server.ListenPort,
|
||||||
|
PersistentKeepalive: setting.PersistentKeepalive,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不同环境下处理文件路径
|
||||||
|
var outPath = "/tmp/" + fmt.Sprintf("%s.conf", clientInfo.Name)
|
||||||
|
var templatePath = "./template/wg.client.conf"
|
||||||
|
if os.Getenv("GIN_MODE") != "release" {
|
||||||
|
outPath = "E:\\Workspace\\Go\\wireguard-dashboard\\template\\" + fmt.Sprintf("%s.conf", clientInfo.Name)
|
||||||
|
templatePath = "E:\\Workspace\\Go\\wireguard-dashboard\\template\\wg.client.conf"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渲染数据
|
||||||
|
parseTemplate, err := Template().Parse(templatePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New("读取模板文件失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Template().Execute(parseTemplate, execData, outPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New("文件渲染失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
return outPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
// random
|
// random
|
||||||
// @description: 随机模式
|
// @description: 随机模式
|
||||||
// @receiver w
|
// @receiver w
|
||||||
|
18
web-src/.vscode/extensions.json
vendored
18
web-src/.vscode/extensions.json
vendored
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"christian-kohler.path-intellisense",
|
|
||||||
"vscode-icons-team.vscode-icons",
|
|
||||||
"davidanson.vscode-markdownlint",
|
|
||||||
"ms-azuretools.vscode-docker",
|
|
||||||
"stylelint.vscode-stylelint",
|
|
||||||
"bradlc.vscode-tailwindcss",
|
|
||||||
"dbaeumer.vscode-eslint",
|
|
||||||
"esbenp.prettier-vscode",
|
|
||||||
"redhat.vscode-yaml",
|
|
||||||
"csstools.postcss",
|
|
||||||
"mikestead.dotenv",
|
|
||||||
"eamodio.gitlens",
|
|
||||||
"antfu.iconify",
|
|
||||||
"Vue.volar"
|
|
||||||
]
|
|
||||||
}
|
|
31
web-src/.vscode/settings.json
vendored
31
web-src/.vscode/settings.json
vendored
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"editor.formatOnType": true,
|
|
||||||
"editor.formatOnSave": true,
|
|
||||||
"[vue]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
||||||
},
|
|
||||||
"editor.tabSize": 2,
|
|
||||||
"editor.formatOnPaste": true,
|
|
||||||
"editor.guides.bracketPairs": "active",
|
|
||||||
"files.autoSave": "afterDelay",
|
|
||||||
"git.confirmSync": false,
|
|
||||||
"workbench.startupEditor": "newUntitledFile",
|
|
||||||
"editor.suggestSelection": "first",
|
|
||||||
"editor.acceptSuggestionOnCommitCharacter": false,
|
|
||||||
"css.lint.propertyIgnoredDueToDisplay": "ignore",
|
|
||||||
"editor.quickSuggestions": {
|
|
||||||
"other": true,
|
|
||||||
"comments": true,
|
|
||||||
"strings": true
|
|
||||||
},
|
|
||||||
"files.associations": {
|
|
||||||
"editor.snippetSuggestions": "top"
|
|
||||||
},
|
|
||||||
"[css]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
||||||
},
|
|
||||||
"editor.codeActionsOnSave": {
|
|
||||||
"source.fixAll.eslint": "explicit"
|
|
||||||
},
|
|
||||||
"iconify.excludes": ["el"]
|
|
||||||
}
|
|
22
web-src/.vscode/vue3.0.code-snippets
vendored
22
web-src/.vscode/vue3.0.code-snippets
vendored
@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"Vue3.0快速生成模板": {
|
|
||||||
"scope": "vue",
|
|
||||||
"prefix": "Vue3.0",
|
|
||||||
"body": [
|
|
||||||
"<template>",
|
|
||||||
"\t<div>test</div>",
|
|
||||||
"</template>\n",
|
|
||||||
"<script lang='ts'>",
|
|
||||||
"export default {",
|
|
||||||
"\tsetup() {",
|
|
||||||
"\t\treturn {}",
|
|
||||||
"\t}",
|
|
||||||
"}",
|
|
||||||
"</script>\n",
|
|
||||||
"<style lang='scss' scoped>\n",
|
|
||||||
"</style>",
|
|
||||||
"$2"
|
|
||||||
],
|
|
||||||
"description": "Vue3.0"
|
|
||||||
}
|
|
||||||
}
|
|
17
web-src/.vscode/vue3.2.code-snippets
vendored
17
web-src/.vscode/vue3.2.code-snippets
vendored
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"Vue3.2+快速生成模板": {
|
|
||||||
"scope": "vue",
|
|
||||||
"prefix": "Vue3.2+",
|
|
||||||
"body": [
|
|
||||||
"<script setup lang='ts'>",
|
|
||||||
"</script>\n",
|
|
||||||
"<template>",
|
|
||||||
"\t<div>test</div>",
|
|
||||||
"</template>\n",
|
|
||||||
"<style lang='scss' scoped>\n",
|
|
||||||
"</style>",
|
|
||||||
"$2"
|
|
||||||
],
|
|
||||||
"description": "Vue3.2+"
|
|
||||||
}
|
|
||||||
}
|
|
20
web-src/.vscode/vue3.3.code-snippets
vendored
20
web-src/.vscode/vue3.3.code-snippets
vendored
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"Vue3.3+defineOptions快速生成模板": {
|
|
||||||
"scope": "vue",
|
|
||||||
"prefix": "Vue3.3+",
|
|
||||||
"body": [
|
|
||||||
"<script setup lang='ts'>",
|
|
||||||
"defineOptions({",
|
|
||||||
"\tname: ''",
|
|
||||||
"})",
|
|
||||||
"</script>\n",
|
|
||||||
"<template>",
|
|
||||||
"\t<div>test</div>",
|
|
||||||
"</template>\n",
|
|
||||||
"<style lang='scss' scoped>\n",
|
|
||||||
"</style>",
|
|
||||||
"$2"
|
|
||||||
],
|
|
||||||
"description": "Vue3.3+defineOptions快速生成模板"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"Version": "5.5.0",
|
"Version": "5.5.0",
|
||||||
"Title": "WG-Dashboard",
|
"Title": "wg-dashboard",
|
||||||
"FixedHeader": true,
|
"FixedHeader": true,
|
||||||
"HiddenSideBar": false,
|
"HiddenSideBar": false,
|
||||||
"MultiTagsCache": false,
|
"MultiTagsCache": false,
|
||||||
|
@ -47,3 +47,8 @@ export const getClientConnects = () => {
|
|||||||
export const offlineClient = (id: string) => {
|
export const offlineClient = (id: string) => {
|
||||||
return http.request<any>("post", baseUri("/client/offline/" + id));
|
return http.request<any>("post", baseUri("/client/offline/" + id));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 发送邮件
|
||||||
|
export const sendMail = (id: string) => {
|
||||||
|
return http.request<any>("post", baseUri("/client/to-email/" + id));
|
||||||
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { http } from "@/utils/http";
|
import { http } from "@/utils/http";
|
||||||
import { baseUri } from "@/api/utils";
|
import { baseUri } from "@/api/utils";
|
||||||
|
import { data } from "autoprefixer";
|
||||||
|
|
||||||
// 获取当前登陆用户信息
|
// 获取当前登陆用户信息
|
||||||
export const getUser = () => {
|
export const getUser = () => {
|
||||||
@ -30,3 +31,8 @@ export const deleteUser = (userId: string) => {
|
|||||||
export const changePassword = (data?: object) => {
|
export const changePassword = (data?: object) => {
|
||||||
return http.request("post", baseUri("/user/change-password"), { data });
|
return http.request("post", baseUri("/user/change-password"), { data });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 生成头像
|
||||||
|
export const generateAvatar = () => {
|
||||||
|
return http.request<any>("post", baseUri("/user/change-avatar"));
|
||||||
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { FormInstance } from "element-plus";
|
import { FormInstance } from "element-plus";
|
||||||
|
import { generateAvatar } from "@/api/user";
|
||||||
|
|
||||||
// 声明 props 类型
|
// 声明 props 类型
|
||||||
export interface FormProps {
|
export interface FormProps {
|
||||||
@ -41,11 +42,29 @@ function getUserEditFormRef() {
|
|||||||
return userEditFormRef.value;
|
return userEditFormRef.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 切换头像
|
||||||
|
const changeAvatar = () => {
|
||||||
|
generateAvatar().then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
userEditForm.value.avatar = res.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
defineExpose({ getUserEditFormRef });
|
defineExpose({ getUserEditFormRef });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-form ref="userEditFormRef" :model="userEditForm" label-width="20%">
|
<el-form ref="userEditFormRef" :model="userEditForm" label-width="20%">
|
||||||
|
<el-form-item prop="avatar">
|
||||||
|
<el-avatar
|
||||||
|
style="cursor: pointer; margin-left: 25%"
|
||||||
|
size="large"
|
||||||
|
fit="cover"
|
||||||
|
:src="userEditForm.avatar"
|
||||||
|
@click="changeAvatar()"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
prop="name"
|
prop="name"
|
||||||
label="名称"
|
label="名称"
|
||||||
|
@ -132,6 +132,7 @@ const getRule = () => {
|
|||||||
rule.value = res.data.rule === "hand";
|
rule.value = res.data.rule === "hand";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
storageLocal().setItem("restart-rule", rule.value);
|
||||||
return rule;
|
return rule;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -163,6 +163,15 @@ class PureHttp {
|
|||||||
resolve(response);
|
resolve(response);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
// 401直接跳转回去
|
||||||
|
if (error.response.status === 401) {
|
||||||
|
router.replace({
|
||||||
|
path: "/login",
|
||||||
|
query: {
|
||||||
|
redirect: router.currentRoute.value.fullPath
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
if (error.response === null || error.response === undefined) {
|
if (error.response === null || error.response === undefined) {
|
||||||
message(error.message, { type: "error" });
|
message(error.message, { type: "error" });
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
import { useServerStoreHook } from "@/store/modules/server";
|
import { useServerStoreHook } from "@/store/modules/server";
|
||||||
import { getSystemLog } from "@/api/dashboard";
|
import { getSystemLog } from "@/api/dashboard";
|
||||||
import { reactive } from "vue";
|
import { reactive } from "vue";
|
||||||
import {getClientConnects, offlineClient} from "@/api/clients";
|
import { getClientConnects, offlineClient } from "@/api/clients";
|
||||||
import {Refresh} from "@element-plus/icons-vue";
|
import { Refresh } from "@element-plus/icons-vue";
|
||||||
import {message} from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "Dashboard"
|
name: "Dashboard"
|
||||||
@ -71,6 +71,7 @@ const offlineClientHandler = (clientID: string) => {
|
|||||||
offlineClient(clientID).then(res => {
|
offlineClient(clientID).then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
message("下线客户端成功", { type: "success" });
|
message("下线客户端成功", { type: "success" });
|
||||||
|
getClientsStatus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -86,7 +87,13 @@ getClientsStatus();
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>操作日志</span>
|
<span>操作日志</span>
|
||||||
<el-button style="float: right" type="primary" :icon="Refresh" @click="refreshClick('systemLog')">刷新</el-button>
|
<el-button
|
||||||
|
style="float: right"
|
||||||
|
type="primary"
|
||||||
|
:icon="Refresh"
|
||||||
|
@click="refreshClick('systemLog')"
|
||||||
|
>刷新</el-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-table
|
<el-table
|
||||||
@ -193,7 +200,13 @@ getClientsStatus();
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>客户端链接状态</span>
|
<span>客户端链接状态</span>
|
||||||
<el-button style="float: right" type="primary" :icon="Refresh" @click="refreshClick('clientStatus')">刷新</el-button>
|
<el-button
|
||||||
|
style="float: right"
|
||||||
|
type="primary"
|
||||||
|
:icon="Refresh"
|
||||||
|
@click="refreshClick('clientStatus')"
|
||||||
|
>刷新</el-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-table
|
<el-table
|
||||||
@ -255,11 +268,7 @@ getClientsStatus();
|
|||||||
min-width="80"
|
min-width="80"
|
||||||
align="center"
|
align="center"
|
||||||
/>
|
/>
|
||||||
<el-table-column
|
<el-table-column label="操作" min-width="80" align="center">
|
||||||
label="操作"
|
|
||||||
min-width="80"
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
v-if="scope.row.isOnline"
|
v-if="scope.row.isOnline"
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
deleteClient,
|
deleteClient,
|
||||||
downloadClient, generateClientIP,
|
downloadClient,
|
||||||
|
generateClientIP,
|
||||||
getClients,
|
getClients,
|
||||||
saveClient
|
saveClient,
|
||||||
|
sendMail
|
||||||
} from "@/api/clients";
|
} from "@/api/clients";
|
||||||
import { h, reactive, ref } from "vue";
|
import { h, reactive, ref } from "vue";
|
||||||
import { addDialog } from "@/components/ReDialog/index";
|
import { addDialog } from "@/components/ReDialog/index";
|
||||||
@ -14,6 +16,7 @@ import "plus-pro-components/es/components/search/style/css";
|
|||||||
import { storageLocal } from "@pureadmin/utils";
|
import { storageLocal } from "@pureadmin/utils";
|
||||||
import { ArrowDown } from "@element-plus/icons-vue";
|
import { ArrowDown } from "@element-plus/icons-vue";
|
||||||
import { ElMessageBox } from "element-plus";
|
import { ElMessageBox } from "element-plus";
|
||||||
|
import { message } from "@/utils/message";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
// name 作为一种规范最好必须写上并且和路由的name保持一致
|
// name 作为一种规范最好必须写上并且和路由的name保持一致
|
||||||
@ -151,6 +154,7 @@ const openAddClientDialog = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
const serverInfo = storageLocal().getItem("server-info");
|
const serverInfo = storageLocal().getItem("server-info");
|
||||||
|
const restartRule = !storageLocal().getItem("restart-rule") ? 1 : 0;
|
||||||
addDialog({
|
addDialog({
|
||||||
width: "40%",
|
width: "40%",
|
||||||
title: "新增",
|
title: "新增",
|
||||||
@ -167,13 +171,14 @@ const openAddClientDialog = () => {
|
|||||||
extraAllowedIPS: "",
|
extraAllowedIPS: "",
|
||||||
endpoint: "",
|
endpoint: "",
|
||||||
useServerDNS: 0,
|
useServerDNS: 0,
|
||||||
enableAfterCreation: 0,
|
enableAfterCreation: restartRule,
|
||||||
keys: {
|
keys: {
|
||||||
privateKey: "",
|
privateKey: "",
|
||||||
publicKey: "",
|
publicKey: "",
|
||||||
presharedKey: ""
|
presharedKey: ""
|
||||||
},
|
},
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
|
offlineMonitoring: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeSure: (done, { options }) => {
|
beforeSure: (done, { options }) => {
|
||||||
@ -212,7 +217,8 @@ const openEditClientDialog = (client?: any) => {
|
|||||||
useServerDNS: client.useServerDNS,
|
useServerDNS: client.useServerDNS,
|
||||||
enableAfterCreation: client.enableAfterCreation,
|
enableAfterCreation: client.enableAfterCreation,
|
||||||
keys: client.keys,
|
keys: client.keys,
|
||||||
enabled: Number(client.enabled)
|
enabled: Number(client.enabled),
|
||||||
|
offlineMonitoring: client.offlineMonitoring
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeSure: (done, { options }) => {
|
beforeSure: (done, { options }) => {
|
||||||
@ -278,6 +284,15 @@ const ellipsis = (str: string) => {
|
|||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 发送到邮件
|
||||||
|
const sendToEmail = (clientID: string) => {
|
||||||
|
sendMail(clientID).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
message("发送邮件成功", { type: "success" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
getClientsApi(clientSearchForm.value);
|
getClientsApi(clientSearchForm.value);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -308,10 +323,13 @@ getClientsApi(clientSearchForm.value);
|
|||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<el-card body-style="padding: inherit" shadow="hover">
|
<el-card body-style="padding: inherit" shadow="hover">
|
||||||
<div class="flex flex-wrap gap-4">
|
<div
|
||||||
|
class="flex flex-wrap gap-4"
|
||||||
|
style="display: flex; justify-content: center"
|
||||||
|
>
|
||||||
<el-card
|
<el-card
|
||||||
v-for="val in clientsList.data"
|
v-for="val in clientsList.data"
|
||||||
style="width: 540px"
|
style="float: left; width: 500px"
|
||||||
shadow="hover"
|
shadow="hover"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
@ -337,6 +355,11 @@ getClientsApi(clientSearchForm.value);
|
|||||||
>下载</el-button
|
>下载</el-button
|
||||||
>
|
>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item>
|
||||||
|
<el-button type="success" @click="sendToEmail(val.id)"
|
||||||
|
>邮件</el-button
|
||||||
|
>
|
||||||
|
</el-dropdown-item>
|
||||||
<el-dropdown-item>
|
<el-dropdown-item>
|
||||||
<el-button
|
<el-button
|
||||||
type="danger"
|
type="danger"
|
||||||
@ -417,7 +440,10 @@ getClientsApi(clientSearchForm.value);
|
|||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
<div class="paginate" style="background-color: #ffffff; margin-top: 5px">
|
<div
|
||||||
|
class="paginate"
|
||||||
|
style="background-color: #ffffff; margin-top: 5px"
|
||||||
|
>
|
||||||
<el-card>
|
<el-card>
|
||||||
<el-pagination
|
<el-pagination
|
||||||
small
|
small
|
||||||
|
@ -4,7 +4,7 @@ import { FormInstance } from "element-plus";
|
|||||||
import { storageLocal } from "@pureadmin/utils";
|
import { storageLocal } from "@pureadmin/utils";
|
||||||
import { userKey } from "@/utils/auth";
|
import { userKey } from "@/utils/auth";
|
||||||
import { clientFormRules } from "@/views/server/component/rules";
|
import { clientFormRules } from "@/views/server/component/rules";
|
||||||
import {generateClientKeys} from "@/api/clients";
|
import { generateClientKeys } from "@/api/clients";
|
||||||
|
|
||||||
// 声明 props 类型
|
// 声明 props 类型
|
||||||
export interface DetailFormProps {
|
export interface DetailFormProps {
|
||||||
@ -26,6 +26,7 @@ export interface DetailFormProps {
|
|||||||
presharedKey: string;
|
presharedKey: string;
|
||||||
};
|
};
|
||||||
enabled: number;
|
enabled: number;
|
||||||
|
offlineMonitoring: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +50,8 @@ const props = withDefaults(defineProps<DetailFormProps>(), {
|
|||||||
publicKey: "",
|
publicKey: "",
|
||||||
presharedKey: ""
|
presharedKey: ""
|
||||||
},
|
},
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
|
offlineMonitoring: 0
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -88,7 +90,10 @@ defineExpose({ getDetailFormRef });
|
|||||||
<el-input v-model="detailForm.name" />
|
<el-input v-model="detailForm.name" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="email" label="邮箱">
|
<el-form-item prop="email" label="邮箱">
|
||||||
<el-input v-model="detailForm.email" />
|
<el-input
|
||||||
|
v-model="detailForm.email"
|
||||||
|
placeholder="可用于离线监听通知或接收客户端配置文件"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="subnetRange" label="子网范围">
|
<el-form-item prop="subnetRange" label="子网范围">
|
||||||
<el-input v-model="detailForm.subnetRange" />
|
<el-input v-model="detailForm.subnetRange" />
|
||||||
@ -146,27 +151,33 @@ defineExpose({ getDetailFormRef });
|
|||||||
v-if="detailForm.id === ''"
|
v-if="detailForm.id === ''"
|
||||||
v-model="detailForm.keys.privateKey"
|
v-model="detailForm.keys.privateKey"
|
||||||
/>
|
/>
|
||||||
<el-input v-else disabled v-model="detailForm.keys.privateKey" />
|
<el-input v-else v-model="detailForm.keys.privateKey" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="publicKey" label="公钥">
|
<el-form-item prop="publicKey" label="公钥">
|
||||||
<el-input
|
<el-input
|
||||||
v-if="detailForm.id === ''"
|
v-if="detailForm.id === ''"
|
||||||
v-model="detailForm.keys.publicKey"
|
v-model="detailForm.keys.publicKey"
|
||||||
/>
|
/>
|
||||||
<el-input v-else disabled v-model="detailForm.keys.publicKey" />
|
<el-input v-else v-model="detailForm.keys.publicKey" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="presharedKey" label="共享密钥">
|
<el-form-item prop="presharedKey" label="共享密钥">
|
||||||
<el-input
|
<el-input
|
||||||
v-if="detailForm.id === ''"
|
v-if="detailForm.id === ''"
|
||||||
v-model="detailForm.keys.presharedKey"
|
v-model="detailForm.keys.presharedKey"
|
||||||
/>
|
/>
|
||||||
<el-input v-else disabled v-model="detailForm.keys.presharedKey" />
|
<el-input v-else v-model="detailForm.keys.presharedKey" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="detailForm.id === ''">
|
<el-form-item v-if="detailForm.id === ''">
|
||||||
<el-button type="primary" size="small" @click="generateClientKeysApi()"
|
<el-button type="primary" size="small" @click="generateClientKeysApi()"
|
||||||
>生成密钥对</el-button
|
>生成密钥对</el-button
|
||||||
>
|
>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item prop="OfflineMonitoring" label="是否启用离线监听">
|
||||||
|
<el-radio-group v-model="detailForm.offlineMonitoring">
|
||||||
|
<el-radio :value="1">是</el-radio>
|
||||||
|
<el-radio :value="0">否</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item prop="useServerDNS" label="是否使用服务端DNS">
|
<el-form-item prop="useServerDNS" label="是否使用服务端DNS">
|
||||||
<el-radio-group v-model="detailForm.useServerDNS">
|
<el-radio-group v-model="detailForm.useServerDNS">
|
||||||
<el-radio :value="1">是</el-radio>
|
<el-radio :value="1">是</el-radio>
|
||||||
|
Loading…
Reference in New Issue
Block a user