Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8fb5d3964a | |||
| 3d92431269 | |||
| f06840eaea | |||
| 906769e21a | |||
| 3641bbe25f | |||
| a39a669d75 | |||
| 9f6771ec09 |
+7
-1
@@ -144,7 +144,7 @@ func (a *APIHandler) getHandler(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonObj(c, *users, nil)
|
jsonObj(c, *users, nil)
|
||||||
case "setting":
|
case "settings":
|
||||||
data, err := a.SettingService.GetAllSetting()
|
data, err := a.SettingService.GetAllSetting()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "", err)
|
jsonMsg(c, "", err)
|
||||||
@@ -298,6 +298,12 @@ func (a *APIHandler) loadPartialData(c *gin.Context, objs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data[obj] = json.RawMessage(config)
|
data[obj] = json.RawMessage(config)
|
||||||
|
case "settings":
|
||||||
|
settings, err := a.SettingService.GetAllSetting()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data[obj] = settings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ func migrateClientSchema(db *gorm.DB) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteOldWebSecret(db *gorm.DB) error {
|
||||||
|
return db.Exec("DELETE FROM settings WHERE key = ?", "webSecret").Error
|
||||||
|
}
|
||||||
|
|
||||||
func changesObj(db *gorm.DB) error {
|
func changesObj(db *gorm.DB) error {
|
||||||
return db.Exec("UPDATE changes SET obj = CAST('\"' || CAST(obj AS TEXT) || '\"' AS BLOB) WHERE actor = ? and obj not like ?", "DepleteJob", "\"%\"").Error
|
return db.Exec("UPDATE changes SET obj = CAST('\"' || CAST(obj AS TEXT) || '\"' AS BLOB) WHERE actor = ? and obj not like ?", "DepleteJob", "\"%\"").Error
|
||||||
}
|
}
|
||||||
@@ -71,6 +75,10 @@ func to1_1(db *gorm.DB) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = deleteOldWebSecret(db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = changesObj(db)
|
err = changesObj(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1.2.0-beta.1
|
1.2.0-beta.2
|
||||||
+3
-3
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/sagernet/sing v0.6.0-beta.9
|
github.com/sagernet/sing v0.6.0-beta.9
|
||||||
github.com/sagernet/sing-box v1.11.0-beta.19
|
github.com/sagernet/sing-box v1.11.0-beta.20
|
||||||
github.com/sagernet/sing-dns v0.4.0-beta.1
|
github.com/sagernet/sing-dns v0.4.0-beta.1
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5
|
github.com/shirou/gopsutil/v3 v3.24.5
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
@@ -91,12 +91,12 @@ require (
|
|||||||
github.com/sagernet/quic-go v0.48.2-beta.1 // indirect
|
github.com/sagernet/quic-go v0.48.2-beta.1 // indirect
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||||
github.com/sagernet/sing-mux v0.3.0-alpha.1 // indirect
|
github.com/sagernet/sing-mux v0.3.0-alpha.1 // indirect
|
||||||
github.com/sagernet/sing-quic v0.4.0-beta.2 // indirect
|
github.com/sagernet/sing-quic v0.4.0-beta.3 // indirect
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7 // indirect
|
github.com/sagernet/sing-shadowsocks v0.2.7 // indirect
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect
|
github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect
|
||||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 // indirect
|
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 // indirect
|
||||||
github.com/sagernet/sing-tun v0.6.0-beta.7.0.20241229131914-aa9d9c62966f // indirect
|
github.com/sagernet/sing-tun v0.6.0-beta.7.0.20241229131914-aa9d9c62966f // indirect
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1 // indirect
|
github.com/sagernet/sing-vmess v0.2.0-beta.2 // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||||
github.com/sagernet/utls v1.6.7 // indirect
|
github.com/sagernet/utls v1.6.7 // indirect
|
||||||
github.com/sagernet/wireguard-go v0.0.1-beta.5 // indirect
|
github.com/sagernet/wireguard-go v0.0.1-beta.5 // indirect
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ github.com/sagernet/sing-box v1.11.0-beta.15 h1:oWcs/PHgKaeWKbTfgz/020KEVvDqQv/t
|
|||||||
github.com/sagernet/sing-box v1.11.0-beta.15/go.mod h1:+QZDsF4HkdiGcMfz+JNOfONLh9CnZjIwJJQNWEzhiaQ=
|
github.com/sagernet/sing-box v1.11.0-beta.15/go.mod h1:+QZDsF4HkdiGcMfz+JNOfONLh9CnZjIwJJQNWEzhiaQ=
|
||||||
github.com/sagernet/sing-box v1.11.0-beta.19 h1:uL2xlXpz4t7BduLbXiLe5QqpyiMhvNNRThBzhTJ4p00=
|
github.com/sagernet/sing-box v1.11.0-beta.19 h1:uL2xlXpz4t7BduLbXiLe5QqpyiMhvNNRThBzhTJ4p00=
|
||||||
github.com/sagernet/sing-box v1.11.0-beta.19/go.mod h1:UXUN/lwRT9mAM8PK7upPOwgqooOV2vU+CcjBfwT1rYg=
|
github.com/sagernet/sing-box v1.11.0-beta.19/go.mod h1:UXUN/lwRT9mAM8PK7upPOwgqooOV2vU+CcjBfwT1rYg=
|
||||||
|
github.com/sagernet/sing-box v1.11.0-beta.20 h1:snuBUv7p7m1eBJKd9Kycnq4TA6V4t6ea2XxZPCEaDAM=
|
||||||
|
github.com/sagernet/sing-box v1.11.0-beta.20/go.mod h1:w5cd6P5pLrF7bGu3Z3k6jkbJqS7ByjK/Y34INVA7k5Q=
|
||||||
github.com/sagernet/sing-dns v0.4.0-beta.1 h1:W1XkdhigwxDOMgMDVB+9kdomCpb7ExsZfB4acPcTZFY=
|
github.com/sagernet/sing-dns v0.4.0-beta.1 h1:W1XkdhigwxDOMgMDVB+9kdomCpb7ExsZfB4acPcTZFY=
|
||||||
github.com/sagernet/sing-dns v0.4.0-beta.1/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8=
|
github.com/sagernet/sing-dns v0.4.0-beta.1/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8=
|
||||||
github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg=
|
github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg=
|
||||||
@@ -194,6 +196,8 @@ github.com/sagernet/sing-quic v0.4.0-alpha.4 h1:P9xAx3nIfcqb9M8jfgs0uLm+VxCcaY++
|
|||||||
github.com/sagernet/sing-quic v0.4.0-alpha.4/go.mod h1:h5RkKTmUhudJKzK7c87FPXD5w1bJjVyxMN9+opZcctA=
|
github.com/sagernet/sing-quic v0.4.0-alpha.4/go.mod h1:h5RkKTmUhudJKzK7c87FPXD5w1bJjVyxMN9+opZcctA=
|
||||||
github.com/sagernet/sing-quic v0.4.0-beta.2 h1:ikoQ7zTR0o/2rlI5H5FeNC0j5bQJJHb1uoyXFRu3yGk=
|
github.com/sagernet/sing-quic v0.4.0-beta.2 h1:ikoQ7zTR0o/2rlI5H5FeNC0j5bQJJHb1uoyXFRu3yGk=
|
||||||
github.com/sagernet/sing-quic v0.4.0-beta.2/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM=
|
github.com/sagernet/sing-quic v0.4.0-beta.2/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM=
|
||||||
|
github.com/sagernet/sing-quic v0.4.0-beta.3 h1:cOBjlhVdRZmBm6hIw1GleERpnTSFdBB2htgx5kQ5uqg=
|
||||||
|
github.com/sagernet/sing-quic v0.4.0-beta.3/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||||
@@ -210,6 +214,8 @@ github.com/sagernet/sing-tun v0.6.0-beta.7.0.20241229131914-aa9d9c62966f h1:dTnX
|
|||||||
github.com/sagernet/sing-tun v0.6.0-beta.7.0.20241229131914-aa9d9c62966f/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
github.com/sagernet/sing-tun v0.6.0-beta.7.0.20241229131914-aa9d9c62966f/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1 h1:5sXQ23uwNlZuDvygzi0dFtnG0Csm/SNqTjAHXJkpuj4=
|
github.com/sagernet/sing-vmess v0.2.0-beta.1 h1:5sXQ23uwNlZuDvygzi0dFtnG0Csm/SNqTjAHXJkpuj4=
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1/go.mod h1:fLyE1emIcvQ5DV8reFWnufquZ7MkCSYM5ThodsR9NrQ=
|
github.com/sagernet/sing-vmess v0.2.0-beta.1/go.mod h1:fLyE1emIcvQ5DV8reFWnufquZ7MkCSYM5ThodsR9NrQ=
|
||||||
|
github.com/sagernet/sing-vmess v0.2.0-beta.2 h1:obAkAL35X7ql4RnGzDg4dBYIRpGXRKqcN4LyLZpZGSs=
|
||||||
|
github.com/sagernet/sing-vmess v0.2.0-beta.2/go.mod h1:HGhf9XUdeE2iOWrX0hQNFgXPbKyGlzpeYFyX0c/pykk=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
||||||
github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8=
|
github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8=
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, login
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = s.restartCoreWithConfig(data)
|
err = s.restartCoreWithConfig(data)
|
||||||
|
case "settings":
|
||||||
|
err = s.SettingService.Save(tx, data)
|
||||||
default:
|
default:
|
||||||
return nil, common.NewError("unknown object: ", obj)
|
return nil, common.NewError("unknown object: ", obj)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ func (s *ServerService) GenKeypair(keyType string, options string) []string {
|
|||||||
case "reality":
|
case "reality":
|
||||||
return s.generateRealityKeyPair()
|
return s.generateRealityKeyPair()
|
||||||
case "wireguard":
|
case "wireguard":
|
||||||
return generateWireGuardKey()
|
return generateWireGuardKey(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{"Failed to generate keypair"}
|
return []string{"Failed to generate keypair"}
|
||||||
@@ -195,10 +195,14 @@ func (s *ServerService) generateRealityKeyPair() []string {
|
|||||||
return []string{"PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey[:]), "PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey[:])}
|
return []string{"PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey[:]), "PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey[:])}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateWireGuardKey() []string {
|
func generateWireGuardKey(pk string) []string {
|
||||||
privateKey, err := wgtypes.GeneratePrivateKey()
|
if len(pk) > 0 {
|
||||||
|
key, _ := wgtypes.ParseKey(pk)
|
||||||
|
return []string{key.PublicKey().String()}
|
||||||
|
}
|
||||||
|
wgKeys, err := wgtypes.GeneratePrivateKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{"Failed to generate wireguard keypair: ", err.Error()}
|
return []string{"Failed to generate wireguard keypair: ", err.Error()}
|
||||||
}
|
}
|
||||||
return []string{"PrivateKey: " + privateKey.String(), "PublicKey: " + privateKey.PublicKey().String()}
|
return []string{"PrivateKey: " + wgKeys.String(), "PublicKey: " + wgKeys.PublicKey().String()}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -351,13 +351,14 @@ func (s *SettingService) SaveConfig(tx *gorm.DB, config json.RawMessage) error {
|
|||||||
return tx.Model(model.Setting{}).Where("key = ?", "config").Update("value", string(configs)).Error
|
return tx.Model(model.Setting{}).Where("key = ?", "config").Update("value", string(configs)).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SettingService) Save(tx *gorm.DB, changes []model.Changes) error {
|
func (s *SettingService) Save(tx *gorm.DB, data json.RawMessage) error {
|
||||||
var err error
|
var err error
|
||||||
for _, change := range changes {
|
var settings map[string]string
|
||||||
key := change.Key
|
err = json.Unmarshal(data, &settings)
|
||||||
var obj string
|
if err != nil {
|
||||||
json.Unmarshal(change.Obj, &obj)
|
return err
|
||||||
|
}
|
||||||
|
for key, obj := range settings {
|
||||||
// Secure file existance check
|
// Secure file existance check
|
||||||
if obj != "" && (key == "webCertFile" ||
|
if obj != "" && (key == "webCertFile" ||
|
||||||
key == "webKeyFile" ||
|
key == "webKeyFile" ||
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "1.2.0-beta.1",
|
"version": "1.2.0-beta.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "1.2.0-beta.1",
|
"version": "1.2.0-beta.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "7.4.47",
|
"@mdi/font": "7.4.47",
|
||||||
"axios": "^1.7.4",
|
"axios": "^1.7.4",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "1.2.0-beta.1",
|
"version": "1.2.0-beta.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
hide-details
|
hide-details
|
||||||
v-model="port">
|
v-model.number="port">
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" sm="6" md="4">
|
<v-col cols="12" sm="6" md="4">
|
||||||
@@ -21,8 +21,9 @@
|
|||||||
label="KeepAlive"
|
label="KeepAlive"
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
|
:suffix="$t('date.s')"
|
||||||
hide-details
|
hide-details
|
||||||
v-model="data.persistent_keepalive_interval">
|
v-model.number="keepAlive">
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -72,6 +73,10 @@ export default {
|
|||||||
port: {
|
port: {
|
||||||
get() { return this.$props.data.port },
|
get() { return this.$props.data.port },
|
||||||
set(v:number) { this.$props.data.port = v > 0 ? v : undefined }
|
set(v:number) { this.$props.data.port = v > 0 ? v : undefined }
|
||||||
|
},
|
||||||
|
keepAlive: {
|
||||||
|
get() { return this.$props.data.persistent_keepalive_interval?? 0 },
|
||||||
|
set(v:number) { this.$props.data.persistent_keepalive_interval = v > 0 ? v : undefined }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,12 +77,12 @@
|
|||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" sm="6" md="4">
|
<v-col cols="12" sm="6" md="4">
|
||||||
<v-text-field
|
<v-switch
|
||||||
label="Rewrite Host"
|
label="Rewrite Host"
|
||||||
placeholder="example.com"
|
|
||||||
v-model="data.masquerade.rewrite_host"
|
v-model="data.masquerade.rewrite_host"
|
||||||
|
color="primary"
|
||||||
hide-details>
|
hide-details>
|
||||||
</v-text-field>
|
</v-switch>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<template v-if="masqueradeType == 'string'">
|
<template v-if="masqueradeType == 'string'">
|
||||||
|
|||||||
@@ -10,6 +10,16 @@
|
|||||||
hide-details>
|
hide-details>
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
<v-col cols="12" sm="8">
|
||||||
|
<v-text-field
|
||||||
|
v-model="options.public_key"
|
||||||
|
disabled
|
||||||
|
:label="$t('tls.pubKey')"
|
||||||
|
append-icon="mdi-refresh"
|
||||||
|
@click:append="getWgPubKey()"
|
||||||
|
hide-details>
|
||||||
|
</v-text-field>
|
||||||
|
</v-col>
|
||||||
<v-col cols="12" sm="8">
|
<v-col cols="12" sm="8">
|
||||||
<v-text-field v-model="address" :label="$t('types.wg.localIp') + ' ' + $t('commaSeparated')" hide-details></v-text-field>
|
<v-text-field v-model="address" :label="$t('types.wg.localIp') + ' ' + $t('commaSeparated')" hide-details></v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
@@ -59,11 +69,11 @@
|
|||||||
<v-col cols="12" sm="6" md="4">
|
<v-col cols="12" sm="6" md="4">
|
||||||
<v-switch v-model="data.system" color="primary" :label="$t('types.wg.sysIf')" hide-details></v-switch>
|
<v-switch v-model="data.system" color="primary" :label="$t('types.wg.sysIf')" hide-details></v-switch>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" sm="6" md="4" v-if="data.name != undefined">
|
<v-col cols="12" sm="6" md="4" v-if="data.system">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('types.wg.ifName')"
|
:label="$t('types.wg.ifName')"
|
||||||
hide-details
|
hide-details
|
||||||
v-model="data.name">
|
v-model="ifName">
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -84,9 +94,6 @@
|
|||||||
<v-list-item>
|
<v-list-item>
|
||||||
<v-switch v-model="optionMtu" color="primary" label="MTU" hide-details></v-switch>
|
<v-switch v-model="optionMtu" color="primary" label="MTU" hide-details></v-switch>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item>
|
|
||||||
<v-switch v-model="optionInterface" color="primary" :label="$t('types.wg.ifName')" hide-details></v-switch>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
@@ -111,8 +118,8 @@
|
|||||||
import Peer from '@/components/WgPeer.vue'
|
import Peer from '@/components/WgPeer.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['data'],
|
props: ['data', 'options'],
|
||||||
emits: ["newWgKey"],
|
emits: ['newWgKey', 'getWgPubKey'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
menu: false,
|
menu: false,
|
||||||
@@ -125,6 +132,11 @@ export default {
|
|||||||
newKey() {
|
newKey() {
|
||||||
this.$emit('newWgKey')
|
this.$emit('newWgKey')
|
||||||
},
|
},
|
||||||
|
getWgPubKey() {
|
||||||
|
const privKey = this.$props.data.private_key
|
||||||
|
if (privKey.length == 0) return
|
||||||
|
this.$emit('getWgPubKey', privKey)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
optionUdp: {
|
optionUdp: {
|
||||||
@@ -143,9 +155,9 @@ export default {
|
|||||||
get(): boolean { return this.$props.data.mtu != undefined },
|
get(): boolean { return this.$props.data.mtu != undefined },
|
||||||
set(v:boolean) { this.$props.data.mtu = v ? 1408 : undefined }
|
set(v:boolean) { this.$props.data.mtu = v ? 1408 : undefined }
|
||||||
},
|
},
|
||||||
optionInterface: {
|
ifName: {
|
||||||
get(): boolean { return this.$props.data.name != undefined },
|
get() { return this.$props.data.name?? '' },
|
||||||
set(v:boolean) { this.$props.data.name = v ? "" : undefined }
|
set(v:string) { this.$props.data.name = v.length > 0 ? v : undefined }
|
||||||
},
|
},
|
||||||
address: {
|
address: {
|
||||||
get() { return this.$props.data.address?.join(',') },
|
get() { return this.$props.data.address?.join(',') },
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<v-text-field v-model="endpoint.tag" :label="$t('objects.tag')" hide-details></v-text-field>
|
<v-text-field v-model="endpoint.tag" :label="$t('objects.tag')" hide-details></v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<Wireguard v-if="endpoint.type == epTypes.Wireguard" :data="endpoint" @newWgKey="newWgKey" />
|
<Wireguard v-if="endpoint.type == epTypes.Wireguard" :data="endpoint" :options="options" @getWgPubKey="getWgPubKey" @newWgKey="newWgKey" />
|
||||||
<Dial :dial="endpoint" :outTags="tags" />
|
<Dial :dial="endpoint" :outTags="tags" />
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@@ -61,9 +61,9 @@ export default {
|
|||||||
endpoint: createEndpoint("wireguard",{ "tag": "" }),
|
endpoint: createEndpoint("wireguard",{ "tag": "" }),
|
||||||
title: "add",
|
title: "add",
|
||||||
tab: "t1",
|
tab: "t1",
|
||||||
link: "",
|
|
||||||
loading: false,
|
loading: false,
|
||||||
epTypes: EpTypes,
|
epTypes: EpTypes,
|
||||||
|
options: <any>{},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -71,21 +71,24 @@ export default {
|
|||||||
if (this.$props.id > 0) {
|
if (this.$props.id > 0) {
|
||||||
const newData = JSON.parse(this.$props.data)
|
const newData = JSON.parse(this.$props.data)
|
||||||
this.endpoint = createEndpoint(newData.type, newData)
|
this.endpoint = createEndpoint(newData.type, newData)
|
||||||
|
this.options = {}
|
||||||
this.title = "edit"
|
this.title = "edit"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const port = RandomUtil.randomIntRange(10000, 60000)
|
const port = RandomUtil.randomIntRange(10000, 60000)
|
||||||
const randomIPoctet = RandomUtil.randomIntRange(1, 255)
|
const randomIPoctet = RandomUtil.randomIntRange(1, 255)
|
||||||
|
const wgKeys = (await this.genWgKey())
|
||||||
this.endpoint = createEndpoint("wireguard",{
|
this.endpoint = createEndpoint("wireguard",{
|
||||||
tag: "wireguard-" + RandomUtil.randomSeq(3),
|
tag: "wireguard-" + RandomUtil.randomSeq(3),
|
||||||
address: ['10.0.0.'+ randomIPoctet.toString() +'/32','fe80::'+ randomIPoctet.toString(16) +'/128'],
|
address: ['10.0.0.'+ randomIPoctet.toString() +'/32','fe80::'+ randomIPoctet.toString(16) +'/128'],
|
||||||
listen_port: port,
|
listen_port: port,
|
||||||
private_key: (await this.genWgKey()).private_key,
|
private_key: wgKeys.private_key,
|
||||||
peers: [{
|
peers: [{
|
||||||
public_key: (await this.genWgKey()).public_key,
|
public_key: (await this.genWgKey()).public_key,
|
||||||
allowed_ips: ['0.0.0.0/0', '::/0']
|
allowed_ips: ['0.0.0.0/0', '::/0']
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
|
this.options.public_key = wgKeys.public_key
|
||||||
this.title = "add"
|
this.title = "add"
|
||||||
}
|
}
|
||||||
this.tab = "t1"
|
this.tab = "t1"
|
||||||
@@ -130,11 +133,20 @@ export default {
|
|||||||
async newWgKey(){
|
async newWgKey(){
|
||||||
const newKeys = await this.genWgKey()
|
const newKeys = await this.genWgKey()
|
||||||
this.endpoint.private_key = newKeys.private_key
|
this.endpoint.private_key = newKeys.private_key
|
||||||
|
this.options.public_key = newKeys.public_key
|
||||||
|
},
|
||||||
|
async getWgPubKey(private_key: string) {
|
||||||
|
this.loading = true
|
||||||
|
const msg = await HttpUtils.get('api/keypairs', { k: "wireguard", o: private_key })
|
||||||
|
if (msg.success) {
|
||||||
|
this.options.public_key = msg.obj
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
visible(newValue) {
|
visible(v) {
|
||||||
if (newValue) {
|
if (v) {
|
||||||
this.updateData()
|
this.updateData()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,55 +5,6 @@ type OBJ = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const FindDiff = {
|
export const FindDiff = {
|
||||||
Config(obj1: OBJ, obj2: OBJ): any[] {
|
|
||||||
const differences: any[] = []
|
|
||||||
|
|
||||||
if(!obj2){
|
|
||||||
return [ { key: "all", obj: obj1 } ]
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key in obj1) {
|
|
||||||
if (obj2.hasOwnProperty(key)) {
|
|
||||||
const value1 = obj1[key]
|
|
||||||
const value2 = obj2[key]
|
|
||||||
|
|
||||||
if (Array.isArray(value1)){
|
|
||||||
value1.forEach((v1,index) => {
|
|
||||||
if(index >= value2.length){
|
|
||||||
differences.push({key: key, action: "new", index: index, obj: v1})
|
|
||||||
} else if(!this.deepCompare(v1,value2[index])) {
|
|
||||||
differences.push({key: key, action: "edit", index: index, obj: v1})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
if (!this.deepCompare(value1,value2)) {
|
|
||||||
differences.push({ key: key, action: "set", obj: value1})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
differences.push({ key: key, action: "set", obj: obj1[key]})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return differences
|
|
||||||
},
|
|
||||||
ArrObj(value1: any[], value2: any[], key: string): any {
|
|
||||||
const differences: any[] = []
|
|
||||||
value1.forEach((v1,index) => {
|
|
||||||
if(index >= value2.length) differences.push({key: key, action: "new", obj: v1})
|
|
||||||
else if(!this.deepCompare(v1,value2[index])) differences.push({key: key, action: "edit", obj: v1})
|
|
||||||
})
|
|
||||||
return differences
|
|
||||||
},
|
|
||||||
Settings(obj1: OBJ, obj2: OBJ): any {
|
|
||||||
const differences: any[] = []
|
|
||||||
for (const key in obj1) {
|
|
||||||
if (obj1[key] != obj2[key]) {
|
|
||||||
differences.push({ key: key, action: "set", obj: obj1[key]})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return differences
|
|
||||||
},
|
|
||||||
deepCompare(obj1: any, obj2: any): boolean {
|
deepCompare(obj1: any, obj2: any): boolean {
|
||||||
// Check if the types of both objects are the same
|
// Check if the types of both objects are the same
|
||||||
if (typeof obj1 !== typeof obj2) {
|
if (typeof obj1 !== typeof obj2) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { FindDiff } from '@/plugins/utils'
|
|
||||||
import HttpUtils from '@/plugins/httputil'
|
import HttpUtils from '@/plugins/httputil'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { push } from 'notivue'
|
import { push } from 'notivue'
|
||||||
@@ -56,15 +55,11 @@ const Data = defineStore('Data', {
|
|||||||
}
|
}
|
||||||
return <Inbound[]>[]
|
return <Inbound[]>[]
|
||||||
},
|
},
|
||||||
async save (object: string, action: string, data: any, userLinks: any[] | null = null, outJsons: any[] | null = null): Promise<boolean> {
|
async save (object: string, action: string, data: any): Promise<boolean> {
|
||||||
let postData = {
|
let postData = {
|
||||||
object: object,
|
object: object,
|
||||||
action: action,
|
action: action,
|
||||||
data: JSON.stringify(data, null, 2),
|
data: JSON.stringify(data, null, 2),
|
||||||
userLinks: userLinks == null ? undefined : JSON.stringify(userLinks),
|
|
||||||
}
|
|
||||||
if (userLinks == null) {
|
|
||||||
delete postData.userLinks
|
|
||||||
}
|
}
|
||||||
const msg = await HttpUtils.post('api/save', postData)
|
const msg = await HttpUtils.post('api/save', postData)
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
@@ -78,7 +73,7 @@ const Data = defineStore('Data', {
|
|||||||
}
|
}
|
||||||
return msg.success
|
return msg.success
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default Data
|
export default Data
|
||||||
@@ -169,7 +169,7 @@ export interface Hysteria2 extends InboundBasics {
|
|||||||
type: string
|
type: string
|
||||||
directory?: string
|
directory?: string
|
||||||
url?: string
|
url?: string
|
||||||
rewrite_host?: string
|
rewrite_host?: boolean
|
||||||
status_code?: number
|
status_code?: number
|
||||||
headers?: Headers[]
|
headers?: Headers[]
|
||||||
content?: string
|
content?: string
|
||||||
|
|||||||
@@ -234,7 +234,6 @@ import Data from '@/store/modules/data'
|
|||||||
import Dial from '@/components/Dial.vue'
|
import Dial from '@/components/Dial.vue'
|
||||||
import { computed, ref, onMounted } from 'vue'
|
import { computed, ref, onMounted } from 'vue'
|
||||||
import { Config, Ntp } from '@/types/config'
|
import { Config, Ntp } from '@/types/config'
|
||||||
import { Client } from '@/types/clients'
|
|
||||||
import { FindDiff } from '@/plugins/utils'
|
import { FindDiff } from '@/plugins/utils'
|
||||||
|
|
||||||
const oldConfig = ref({})
|
const oldConfig = ref({})
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row align="center" justify="center" style="margin-bottom: 10px;">
|
<v-row align="center" justify="center" style="margin-bottom: 10px;">
|
||||||
<v-col cols="auto">
|
<v-col cols="auto">
|
||||||
<v-btn color="primary" @click="saveChanges" :loading="loading" :disabled="!stateChange">
|
<v-btn color="primary" @click="save" :loading="loading" :disabled="!stateChange">
|
||||||
{{ $t('actions.save') }}
|
{{ $t('actions.save') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
@@ -152,11 +152,12 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useLocale } from 'vuetify'
|
import { useLocale } from 'vuetify'
|
||||||
import { languages } from '@/locales'
|
import { i18n, languages } from '@/locales'
|
||||||
import { Ref, computed, inject, onMounted, ref } from 'vue'
|
import { Ref, computed, inject, onMounted, ref } from 'vue'
|
||||||
import HttpUtils from '@/plugins/httputil'
|
import HttpUtils from '@/plugins/httputil'
|
||||||
import { FindDiff } from '@/plugins/utils'
|
import { FindDiff } from '@/plugins/utils'
|
||||||
import SubJsonExtVue from '@/components/SubJsonExt.vue'
|
import SubJsonExtVue from '@/components/SubJsonExt.vue'
|
||||||
|
import { push } from 'notivue'
|
||||||
const locale = useLocale()
|
const locale = useLocale()
|
||||||
const tab = ref("t1")
|
const tab = ref("t1")
|
||||||
const loading:Ref = inject('loading')?? ref(false)
|
const loading:Ref = inject('loading')?? ref(false)
|
||||||
@@ -195,22 +196,28 @@ const changeLocale = (l: any) => {
|
|||||||
|
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const msg = await HttpUtils.get('api/setting')
|
const msg = await HttpUtils.get('api/settings')
|
||||||
loading.value = false
|
loading.value = false
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
settings.value = msg.obj
|
setData(msg.obj)
|
||||||
oldSettings.value = { ...msg.obj }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveChanges = async () => {
|
const setData = (data: any) => {
|
||||||
|
settings.value = data
|
||||||
|
oldSettings.value = { ...data }
|
||||||
|
}
|
||||||
|
|
||||||
|
const save = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const diff = {
|
const msg = await HttpUtils.post('api/save', { object: 'settings', action: 'set', data: JSON.stringify(settings.value) })
|
||||||
settings: JSON.stringify(FindDiff.Settings(settings.value,oldSettings.value)),
|
|
||||||
}
|
|
||||||
const msg = await HttpUtils.post('api/save', diff)
|
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
loadData()
|
push.success({
|
||||||
|
title: i18n.global.t('success'),
|
||||||
|
duration: 5000,
|
||||||
|
message: i18n.global.t('actions.set') + " " + i18n.global.t('pages.settings')
|
||||||
|
})
|
||||||
|
setData(msg.obj.settings)
|
||||||
}
|
}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -224,7 +224,7 @@ install_s-ui() {
|
|||||||
tar zxvf s-ui-linux-$(arch).tar.gz
|
tar zxvf s-ui-linux-$(arch).tar.gz
|
||||||
rm s-ui-linux-$(arch).tar.gz -f
|
rm s-ui-linux-$(arch).tar.gz -f
|
||||||
|
|
||||||
chmod +x s-ui/sui /s-ui/s-ui.sh
|
chmod +x s-ui/sui s-ui/s-ui.sh
|
||||||
cp s-ui/s-ui.sh /usr/bin/s-ui
|
cp s-ui/s-ui.sh /usr/bin/s-ui
|
||||||
cp -rf s-ui /usr/local/
|
cp -rf s-ui /usr/local/
|
||||||
cp -f s-ui/*.service /etc/systemd/system/
|
cp -f s-ui/*.service /etc/systemd/system/
|
||||||
@@ -236,7 +236,7 @@ install_s-ui() {
|
|||||||
systemctl enable s-ui --now
|
systemctl enable s-ui --now
|
||||||
|
|
||||||
echo -e "${green}s-ui v${last_version}${plain} installation finished, it is up and running now..."
|
echo -e "${green}s-ui v${last_version}${plain} installation finished, it is up and running now..."
|
||||||
echo -e "You may access the Panel with following URL(s):${yellow}"
|
echo -e "You may access the Panel with following URL(s):${green}"
|
||||||
/usr/local/s-ui/sui uri
|
/usr/local/s-ui/sui uri
|
||||||
echo -e "${plain}"
|
echo -e "${plain}"
|
||||||
echo -e ""
|
echo -e ""
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ set_setting() {
|
|||||||
|
|
||||||
view_setting() {
|
view_setting() {
|
||||||
/usr/local/s-ui/sui setting -show
|
/usr/local/s-ui/sui setting -show
|
||||||
|
view_uri
|
||||||
before_show_menu
|
before_show_menu
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +262,7 @@ view_uri() {
|
|||||||
before_show_menu
|
before_show_menu
|
||||||
fi
|
fi
|
||||||
LOGI "You may access the Panel with following URL(s):"
|
LOGI "You may access the Panel with following URL(s):"
|
||||||
echo -e "${yellow}${info}${reset}"
|
echo -e "${green}${info}${plain}"
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
@@ -850,7 +851,7 @@ show_menu() {
|
|||||||
check_install && set_setting
|
check_install && set_setting
|
||||||
;;
|
;;
|
||||||
10)
|
10)
|
||||||
check_install && view_setting && view_uri
|
check_install && view_setting
|
||||||
;;
|
;;
|
||||||
11)
|
11)
|
||||||
check_install && start s-ui
|
check_install && start s-ui
|
||||||
|
|||||||
Reference in New Issue
Block a user