move LinkGenerator ro backend
This commit is contained in:
+1
-2
@@ -88,8 +88,7 @@ func (a *APIHandler) postHandler(c *gin.Context) {
|
|||||||
obj := c.Request.FormValue("object")
|
obj := c.Request.FormValue("object")
|
||||||
act := c.Request.FormValue("action")
|
act := c.Request.FormValue("action")
|
||||||
data := c.Request.FormValue("data")
|
data := c.Request.FormValue("data")
|
||||||
userLinks := c.Request.FormValue("userLinks")
|
objs, err := a.ConfigService.Save(obj, act, json.RawMessage(data), loginUser, hostname)
|
||||||
objs, err := a.ConfigService.Save(obj, act, json.RawMessage(data), json.RawMessage(userLinks), loginUser, hostname)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "save", err)
|
jsonMsg(c, "save", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -90,7 +90,25 @@ func moveJsonToDb(db *gorm.DB) error {
|
|||||||
db.Raw("select id,addrs,out_json from inbound_data where tag = ?", tag).Find(&inbData)
|
db.Raw("select id,addrs,out_json from inbound_data where tag = ?", tag).Find(&inbData)
|
||||||
if inbData.Id > 0 {
|
if inbData.Id > 0 {
|
||||||
inbObj["out_json"] = inbData.OutJson
|
inbObj["out_json"] = inbData.OutJson
|
||||||
inbObj["addrs"] = inbData.Addrs
|
var addrs []map[string]interface{}
|
||||||
|
json.Unmarshal(inbData.Addrs, &addrs)
|
||||||
|
for index, addr := range addrs {
|
||||||
|
if tlsEnable, ok := addr["tls"].(bool); ok {
|
||||||
|
newTls := map[string]interface{}{
|
||||||
|
"enabled": tlsEnable,
|
||||||
|
}
|
||||||
|
if insecure, ok := addr["insecure"].(bool); ok {
|
||||||
|
newTls["insecure"] = insecure
|
||||||
|
delete(addrs[index], "insecure")
|
||||||
|
}
|
||||||
|
if sni, ok := addr["server_name"].(string); ok {
|
||||||
|
newTls["server_name"] = sni
|
||||||
|
delete(addrs[index], "server_name")
|
||||||
|
}
|
||||||
|
addrs[index]["tls"] = newTls
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inbObj["addrs"] = addrs
|
||||||
} else {
|
} else {
|
||||||
inbObj["out_json"] = json.RawMessage("{}")
|
inbObj["out_json"] = json.RawMessage("{}")
|
||||||
inbObj["addrs"] = json.RawMessage("[]")
|
inbObj["addrs"] = json.RawMessage("[]")
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ func (i Inbound) MarshalFull() (*map[string]interface{}, error) {
|
|||||||
combined["out_json"] = i.OutJson
|
combined["out_json"] = i.OutJson
|
||||||
|
|
||||||
if i.Options != nil {
|
if i.Options != nil {
|
||||||
var restFields map[string]json.RawMessage
|
var restFields map[string]interface{}
|
||||||
if err := json.Unmarshal(i.Options, &restFields); err != nil {
|
if err := json.Unmarshal(i.Options, &restFields); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+117
-17
@@ -5,6 +5,7 @@ import (
|
|||||||
"s-ui/database"
|
"s-ui/database"
|
||||||
"s-ui/database/model"
|
"s-ui/database/model"
|
||||||
"s-ui/logger"
|
"s-ui/logger"
|
||||||
|
"s-ui/util"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -24,7 +25,7 @@ func (s *ClientService) GetAll() ([]model.Client, error) {
|
|||||||
return clients, nil
|
return clients, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage) ([]uint, error) {
|
func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage, hostname string) ([]uint, error) {
|
||||||
var err error
|
var err error
|
||||||
var inboundIds []uint
|
var inboundIds []uint
|
||||||
|
|
||||||
@@ -39,6 +40,10 @@ func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage) ([]u
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
err = s.updateLinksWithFixedInbounds(tx, []*model.Client{&client}, inboundIds, hostname)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
err = tx.Save(&client).Error
|
err = tx.Save(&client).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -67,33 +72,128 @@ func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage) ([]u
|
|||||||
return inboundIds, nil
|
return inboundIds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClientService) UpdateLinks(tx *gorm.DB, links json.RawMessage) error {
|
func (s *ClientService) updateLinksWithFixedInbounds(tx *gorm.DB, clients []*model.Client, inbounIds []uint, hostname string) error {
|
||||||
var userLinks []interface{}
|
var err error
|
||||||
err := json.Unmarshal(links, &userLinks)
|
var inbounds []model.Inbound
|
||||||
|
|
||||||
|
// Zero inbounds means removing local links only
|
||||||
|
if len(inbounIds) > 0 {
|
||||||
|
err = tx.Model(model.Inbound{}).Preload("Tls").Where("id in ? and type in ?", inbounIds, util.InboundTypeWithLink).Find(&inbounds).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for index, client := range clients {
|
||||||
|
var clientLinks, newClientLinks []map[string]string
|
||||||
|
json.Unmarshal(client.Links, &clientLinks)
|
||||||
|
|
||||||
|
for _, inbound := range inbounds {
|
||||||
|
newLinks := util.LinkGenerator(client.Config, &inbound, hostname)
|
||||||
|
for _, newLink := range newLinks {
|
||||||
|
newClientLinks = append(newClientLinks, map[string]string{
|
||||||
|
"remark": inbound.Tag,
|
||||||
|
"type": "local",
|
||||||
|
"uri": newLink,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add no local links
|
||||||
|
for _, clientLink := range clientLinks {
|
||||||
|
if clientLink["type"] != "local" {
|
||||||
|
newClientLinks = append(newClientLinks, clientLink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clients[index].Links, err = json.MarshalIndent(newClientLinks, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ClientService) UpdateClientsOnInboundDelete(tx *gorm.DB, id uint, tag string) error {
|
||||||
|
var clients []model.Client
|
||||||
|
err := tx.Table("clients").
|
||||||
|
Where("EXISTS (SELECT 1 FROM json_each(clients.inbounds) WHERE json_each.value = ?)", id).
|
||||||
|
Find(&clients).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, userLink := range userLinks {
|
for _, client := range clients {
|
||||||
userLinkData, _ := userLink.(map[string]interface{})
|
// Delete inbounds
|
||||||
userId, _ := userLinkData["id"].(float64)
|
var clientInbounds, newClientInbounds []uint
|
||||||
links, err := json.MarshalIndent(userLinkData["links"], "", " ")
|
json.Unmarshal(client.Inbounds, &clientInbounds)
|
||||||
|
for _, clientInbound := range clientInbounds {
|
||||||
|
if clientInbound != id {
|
||||||
|
newClientInbounds = append(newClientInbounds, clientInbound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.Inbounds, err = json.MarshalIndent(newClientInbounds, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if inbounds, ok := userLinkData["inbounds"]; ok {
|
// Delete links
|
||||||
inbounds, err := json.MarshalIndent(inbounds, "", " ")
|
var clientLinks, newClientLinks []map[string]string
|
||||||
if err != nil {
|
json.Unmarshal(client.Links, &clientLinks)
|
||||||
return err
|
for _, clientLink := range clientLinks {
|
||||||
}
|
if clientLink["remark"] != tag {
|
||||||
err = tx.Model(model.Client{}).Where("id = ?", uint(userId)).Update("inbounds", inbounds).Error
|
newClientLinks = append(newClientLinks, clientLink)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = tx.Model(model.Client{}).Where("id = ?", uint(userId)).Update("links", links).Error
|
client.Links, err = json.MarshalIndent(newClientLinks, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = tx.Save(&client).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ClientService) UpdateLinksByInboundChange(tx *gorm.DB, inbounIds []uint, hostname string) error {
|
||||||
|
var inbounds []model.Inbound
|
||||||
|
err := tx.Model(model.Inbound{}).Preload("Tls").Where("id in ? and type in ?", inbounIds, util.InboundTypeWithLink).Find(&inbounds).Error
|
||||||
|
if err != nil && err != gorm.ErrRecordNotFound {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, inbound := range inbounds {
|
||||||
|
var clients []model.Client
|
||||||
|
err = tx.Table("clients").
|
||||||
|
Where("EXISTS (SELECT 1 FROM json_each(clients.inbounds) WHERE json_each.value = ?)", inbound.Id).
|
||||||
|
Find(&clients).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, client := range clients {
|
||||||
|
var clientLinks, newClientLinks []map[string]string
|
||||||
|
json.Unmarshal(client.Links, &clientLinks)
|
||||||
|
newLinks := util.LinkGenerator(client.Config, &inbound, hostname)
|
||||||
|
for _, newLink := range newLinks {
|
||||||
|
newClientLinks = append(newClientLinks, map[string]string{
|
||||||
|
"remark": inbound.Tag,
|
||||||
|
"type": "local",
|
||||||
|
"uri": newLink,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, clientLink := range clientLinks {
|
||||||
|
if clientLink["remark"] != inbound.Tag {
|
||||||
|
newClientLinks = append(newClientLinks, clientLink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Links, err = json.MarshalIndent(newClientLinks, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = tx.Save(&client).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-12
@@ -123,9 +123,10 @@ func (s *ConfigService) StopCore() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userLinks json.RawMessage, loginUser string, hostname string) ([]string, error) {
|
func (s *ConfigService) Save(obj string, act string, data json.RawMessage, loginUser string, hostname string) ([]string, error) {
|
||||||
var err error
|
var err error
|
||||||
var inboundIds []uint
|
var inboundIds []uint
|
||||||
|
var inboundId uint
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
tx := db.Begin()
|
tx := db.Begin()
|
||||||
@@ -139,11 +140,11 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userL
|
|||||||
|
|
||||||
switch obj {
|
switch obj {
|
||||||
case "clients":
|
case "clients":
|
||||||
inboundIds, err = s.ClientService.Save(tx, act, data)
|
inboundIds, err = s.ClientService.Save(tx, act, data, hostname)
|
||||||
case "tls":
|
case "tls":
|
||||||
inboundIds, err = s.TlsService.Save(tx, act, data)
|
inboundIds, err = s.TlsService.Save(tx, act, data)
|
||||||
case "inbounds":
|
case "inbounds":
|
||||||
err = s.InboundService.Save(tx, act, data, hostname)
|
inboundId, err = s.InboundService.Save(tx, act, data, hostname)
|
||||||
case "outbounds":
|
case "outbounds":
|
||||||
err = s.OutboundService.Save(tx, act, data)
|
err = s.OutboundService.Save(tx, act, data)
|
||||||
case "endpoints":
|
case "endpoints":
|
||||||
@@ -161,13 +162,6 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userL
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(userLinks) > 0 {
|
|
||||||
err = s.ClientService.UpdateLinks(tx, userLinks)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dt := time.Now().Unix()
|
dt := time.Now().Unix()
|
||||||
err = tx.Create(&model.Changes{
|
err = tx.Create(&model.Changes{
|
||||||
DateTime: dt,
|
DateTime: dt,
|
||||||
@@ -188,8 +182,25 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userL
|
|||||||
// Update side changes
|
// Update side changes
|
||||||
|
|
||||||
// Update client links
|
// Update client links
|
||||||
if len(userLinks) > 0 {
|
if obj == "tls" && len(inboundIds) > 0 {
|
||||||
err = s.ClientService.UpdateLinks(tx, userLinks)
|
err = s.ClientService.UpdateLinksByInboundChange(tx, inboundIds, hostname)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
objs = append(objs, "clients")
|
||||||
|
}
|
||||||
|
if obj == "inbounds" && act != "add" {
|
||||||
|
switch act {
|
||||||
|
case "edit":
|
||||||
|
err = s.ClientService.UpdateLinksByInboundChange(tx, []uint{inboundId}, hostname)
|
||||||
|
case "del":
|
||||||
|
var tag string
|
||||||
|
err = json.Unmarshal(data, &tag)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = s.ClientService.UpdateClientsOnInboundDelete(tx, inboundId, tag)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-15
@@ -94,8 +94,13 @@ func (j *JsonService) getData(subId string) (*model.Client, []*model.Inbound, er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
var clientInbounds []uint
|
||||||
|
err = json.Unmarshal(client.Inbounds, &clientInbounds)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
var inbounds []*model.Inbound
|
var inbounds []*model.Inbound
|
||||||
err = db.Model(model.Inbound{}).Where("tag in ?", client.Inbounds).Find(&inbounds).Error
|
err = db.Model(model.Inbound{}).Where("id in ?", clientInbounds).Find(&inbounds).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -156,22 +161,14 @@ func (j *JsonService) getOutbounds(clientConfig json.RawMessage, inbounds []*mod
|
|||||||
newOut["server_port"] = int(port)
|
newOut["server_port"] = int(port)
|
||||||
|
|
||||||
// Override TLS
|
// Override TLS
|
||||||
newTls, overrideTls := addr["tls"].(bool)
|
outTls, _ := newOut["tls"].(map[string]interface{})
|
||||||
if overrideTls {
|
if addrTls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||||
tlsIf := map[string]interface{}{}
|
for key, value := range addrTls {
|
||||||
if newTls {
|
outTls[key] = value
|
||||||
tlsIf["enabled"] = true
|
|
||||||
newSNI, overrideSNI := addr["server_name"].(string)
|
|
||||||
if overrideSNI {
|
|
||||||
tlsIf["server_name"] = newSNI
|
|
||||||
}
|
|
||||||
newInsecure, overrideInsecure := addr["insecure"].(bool)
|
|
||||||
if overrideInsecure {
|
|
||||||
tlsIf["insecure"] = newInsecure
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
newOut["tls"] = tlsIf
|
|
||||||
}
|
}
|
||||||
|
newOut["tls"] = outTls
|
||||||
|
|
||||||
remark, _ := addr["remark"].(string)
|
remark, _ := addr["remark"].(string)
|
||||||
newTag := fmt.Sprintf("%d.%s%s", index+1, tag, remark)
|
newTag := fmt.Sprintf("%d.%s%s", index+1, tag, remark)
|
||||||
newOut["tag"] = newTag
|
newOut["tag"] = newTag
|
||||||
|
|||||||
@@ -0,0 +1,510 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"s-ui/database/model"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var InboundTypeWithLink = []string{"shadowsocks", "naive", "hysteria", "hysteria2", "tuic", "vless", "trojan", "vmess"}
|
||||||
|
|
||||||
|
func LinkGenerator(clientConfig json.RawMessage, i *model.Inbound, hostname string) []string {
|
||||||
|
inbound, err := i.MarshalFull()
|
||||||
|
if err != nil {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tls map[string]interface{}
|
||||||
|
if i.TlsId > 0 {
|
||||||
|
json.Unmarshal(i.Tls.Client, &tls)
|
||||||
|
}
|
||||||
|
|
||||||
|
var userConfig map[string]map[string]interface{}
|
||||||
|
if err := json.Unmarshal(clientConfig, &userConfig); err != nil {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var Addrs []map[string]interface{}
|
||||||
|
json.Unmarshal(i.Addrs, &Addrs)
|
||||||
|
fmt.Printf("AddrsArray: %+v\n", Addrs)
|
||||||
|
if len(Addrs) == 0 {
|
||||||
|
Addrs = append(Addrs, map[string]interface{}{
|
||||||
|
"server": hostname,
|
||||||
|
"server_port": (*inbound)["listen_port"],
|
||||||
|
"remark": i.Tag,
|
||||||
|
})
|
||||||
|
if i.TlsId > 0 {
|
||||||
|
Addrs[0]["tls"] = tls
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for index, addr := range Addrs {
|
||||||
|
addrRemark, _ := addr["remark"].(string)
|
||||||
|
Addrs[index]["remark"] = i.Tag + addrRemark
|
||||||
|
if addrTls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||||
|
newTls := map[string]interface{}{}
|
||||||
|
if oldTls, hasOldTls := tls["tls"].(map[string]interface{}); hasOldTls {
|
||||||
|
for k, v := range oldTls {
|
||||||
|
newTls[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Override tls
|
||||||
|
for k, v := range addrTls {
|
||||||
|
newTls[k] = v
|
||||||
|
}
|
||||||
|
Addrs[index]["tls"] = newTls
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch i.Type {
|
||||||
|
case "shadowsocks":
|
||||||
|
return shadowsocksLink(userConfig, *inbound, Addrs)
|
||||||
|
case "naive":
|
||||||
|
return naiveLink(userConfig["naive"], *inbound, Addrs)
|
||||||
|
case "hysteria":
|
||||||
|
return hysteriaLink(userConfig["hysteria"], *inbound, Addrs)
|
||||||
|
case "hysteria2":
|
||||||
|
return hysteria2Link(userConfig["hysteria2"], *inbound, Addrs)
|
||||||
|
case "tuic":
|
||||||
|
return tuicLink(userConfig["tuic"], *inbound, Addrs)
|
||||||
|
case "vless":
|
||||||
|
return vlessLink(userConfig["vless"], *inbound, Addrs)
|
||||||
|
case "trojan":
|
||||||
|
return trojanLink(userConfig["trojan"], *inbound, Addrs)
|
||||||
|
case "vmess":
|
||||||
|
return vmessLink(userConfig["vmess"], *inbound, Addrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func shadowsocksLink(
|
||||||
|
userConfig map[string]map[string]interface{},
|
||||||
|
inbound map[string]interface{},
|
||||||
|
addrs []map[string]interface{}) []string {
|
||||||
|
|
||||||
|
var userPass []string
|
||||||
|
method, _ := inbound["method"].(string)
|
||||||
|
var pass string
|
||||||
|
if method == "2022-blake3-aes-128-gcm" {
|
||||||
|
pass, _ = userConfig["shadowsocks16"]["password"].(string)
|
||||||
|
} else {
|
||||||
|
pass, _ = userConfig["shadowsocks"]["password"].(string)
|
||||||
|
}
|
||||||
|
userPass = append(userPass, pass)
|
||||||
|
|
||||||
|
if strings.HasPrefix(method, "2022") {
|
||||||
|
inbPass, _ := inbound["password"].(string)
|
||||||
|
userPass = append(userPass, inbPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
uriBase := fmt.Sprintf("ss://%s", toBase64([]byte(fmt.Sprintf("%s:%s", method, strings.Join(userPass, ":")))))
|
||||||
|
|
||||||
|
var links []string
|
||||||
|
for _, addr := range addrs {
|
||||||
|
port, _ := addr["server_port"].(float64)
|
||||||
|
links = append(links, fmt.Sprintf("%s@%s:%d", uriBase, addr["server"].(string), uint(port)))
|
||||||
|
}
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
func naiveLink(
|
||||||
|
userConfig map[string]interface{},
|
||||||
|
inbound map[string]interface{},
|
||||||
|
addrs []map[string]interface{}) []string {
|
||||||
|
|
||||||
|
password, _ := userConfig["password"].(string)
|
||||||
|
username, _ := userConfig["username"].(string)
|
||||||
|
|
||||||
|
baseUri := "http2://"
|
||||||
|
var links []string
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
params := map[string]string{}
|
||||||
|
params["padding"] = "1"
|
||||||
|
if tls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||||
|
if sni, ok := tls["server_name"].(string); ok {
|
||||||
|
params["peer"] = sni
|
||||||
|
}
|
||||||
|
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||||
|
alpnList := make([]string, len(alpn))
|
||||||
|
for i, v := range alpn {
|
||||||
|
alpnList[i] = v.(string)
|
||||||
|
}
|
||||||
|
params["alpn"] = strings.Join(alpnList, ",")
|
||||||
|
}
|
||||||
|
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||||
|
params["allowInsecure"] = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tfo, ok := inbound["tcp_fast_open"].(bool); ok && tfo {
|
||||||
|
params["tfo"] = "1"
|
||||||
|
} else {
|
||||||
|
params["tfo"] = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
port, _ := addr["server_port"].(float64)
|
||||||
|
uri := baseUri + toBase64([]byte(fmt.Sprintf("%s:%s@%s:%d", username, password, addr["server"].(string), uint(port))))
|
||||||
|
links = append(links, addParams(uri, params, addr["remark"].(string)))
|
||||||
|
}
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
func hysteriaLink(
|
||||||
|
userConfig map[string]interface{},
|
||||||
|
inbound map[string]interface{},
|
||||||
|
addrs []map[string]interface{}) []string {
|
||||||
|
|
||||||
|
baseUri := "hysteria://"
|
||||||
|
var links []string
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
params := map[string]string{}
|
||||||
|
if upmbps, ok := inbound["up_mbps"].(string); ok {
|
||||||
|
params["up_mbps"] = upmbps
|
||||||
|
}
|
||||||
|
if downmbps, ok := inbound["down_mbps"].(string); ok {
|
||||||
|
params["down_mbps"] = downmbps
|
||||||
|
}
|
||||||
|
if auth, ok := userConfig["auth_str"].(string); ok {
|
||||||
|
params["auth"] = auth
|
||||||
|
}
|
||||||
|
if tls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||||
|
if sni, ok := tls["server_name"].(string); ok {
|
||||||
|
params["peer"] = sni
|
||||||
|
}
|
||||||
|
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||||
|
alpnList := make([]string, len(alpn))
|
||||||
|
for i, v := range alpn {
|
||||||
|
alpnList[i] = v.(string)
|
||||||
|
}
|
||||||
|
params["alpn"] = strings.Join(alpnList, ",")
|
||||||
|
}
|
||||||
|
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||||
|
params["allowInsecure"] = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if obfs, ok := inbound["obfs"].(string); ok {
|
||||||
|
params["obfs"] = obfs
|
||||||
|
}
|
||||||
|
if tfo, ok := inbound["tcp_fast_open"].(bool); ok && tfo {
|
||||||
|
params["fastopen"] = "1"
|
||||||
|
} else {
|
||||||
|
params["fastopen"] = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
port, _ := addr["server_port"].(float64)
|
||||||
|
uri := fmt.Sprintf("%s%s:%d", baseUri, addr["server"].(string), uint(port))
|
||||||
|
links = append(links, addParams(uri, params, addr["remark"].(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
func hysteria2Link(
|
||||||
|
userConfig map[string]interface{},
|
||||||
|
inbound map[string]interface{},
|
||||||
|
addrs []map[string]interface{}) []string {
|
||||||
|
|
||||||
|
password, _ := userConfig["password"].(string)
|
||||||
|
baseUri := fmt.Sprintf("%s%s@", "hysteria2://", password)
|
||||||
|
var links []string
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
params := map[string]string{}
|
||||||
|
if upmbps, ok := inbound["up_mbps"].(string); ok {
|
||||||
|
params["up_mbps"] = upmbps
|
||||||
|
}
|
||||||
|
if downmbps, ok := inbound["down_mbps"].(string); ok {
|
||||||
|
params["down_mbps"] = downmbps
|
||||||
|
}
|
||||||
|
if tls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||||
|
if sni, ok := tls["server_name"].(string); ok {
|
||||||
|
params["sni"] = sni
|
||||||
|
}
|
||||||
|
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||||
|
alpnList := make([]string, len(alpn))
|
||||||
|
for i, v := range alpn {
|
||||||
|
alpnList[i] = v.(string)
|
||||||
|
}
|
||||||
|
params["alpn"] = strings.Join(alpnList, ",")
|
||||||
|
}
|
||||||
|
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||||
|
params["allowInsecure"] = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if obfs, ok := inbound["obfs"].(map[string]interface{}); ok {
|
||||||
|
if obfsType, ok := obfs["type"].(string); ok {
|
||||||
|
params["obfs"] = obfsType
|
||||||
|
}
|
||||||
|
if obfsPassword, ok := obfs["password"].(string); ok {
|
||||||
|
params["obfs-password"] = obfsPassword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tfo, ok := inbound["tcp_fast_open"].(bool); ok && tfo {
|
||||||
|
params["fastopen"] = "1"
|
||||||
|
} else {
|
||||||
|
params["fastopen"] = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
port, _ := addr["server_port"].(float64)
|
||||||
|
uri := fmt.Sprintf("%s%s:%d", baseUri, addr["server"].(string), uint(port))
|
||||||
|
links = append(links, addParams(uri, params, addr["remark"].(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
func tuicLink(
|
||||||
|
userConfig map[string]interface{},
|
||||||
|
inbound map[string]interface{},
|
||||||
|
addrs []map[string]interface{}) []string {
|
||||||
|
|
||||||
|
password, _ := userConfig["password"].(string)
|
||||||
|
uuid, _ := userConfig["uuid"].(string)
|
||||||
|
baseUri := fmt.Sprintf("%s%s:%s@", "tuic://", uuid, password)
|
||||||
|
var links []string
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
params := map[string]string{}
|
||||||
|
if tls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||||
|
if sni, ok := tls["server_name"].(string); ok {
|
||||||
|
params["sni"] = sni
|
||||||
|
}
|
||||||
|
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||||
|
alpnList := make([]string, len(alpn))
|
||||||
|
for i, v := range alpn {
|
||||||
|
alpnList[i] = v.(string)
|
||||||
|
}
|
||||||
|
params["alpn"] = strings.Join(alpnList, ",")
|
||||||
|
}
|
||||||
|
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||||
|
params["allowInsecure"] = "1"
|
||||||
|
}
|
||||||
|
if disableSni, ok := tls["disable_sni"].(bool); ok && disableSni {
|
||||||
|
params["disableSni"] = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if congestionControl, ok := inbound["congestion_control"].(string); ok {
|
||||||
|
params["congestion_control"] = congestionControl
|
||||||
|
}
|
||||||
|
|
||||||
|
port, _ := addr["server_port"].(float64)
|
||||||
|
uri := fmt.Sprintf("%s%s:%d", baseUri, addr["server"].(string), uint(port))
|
||||||
|
links = append(links, addParams(uri, params, addr["remark"].(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
func vlessLink(
|
||||||
|
userConfig map[string]interface{},
|
||||||
|
inbound map[string]interface{},
|
||||||
|
addrs []map[string]interface{}) []string {
|
||||||
|
|
||||||
|
uuid, _ := userConfig["uuid"].(string)
|
||||||
|
baseParams := getTransportParams(inbound["transport"])
|
||||||
|
var links []string
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
params := baseParams
|
||||||
|
if tls, ok := addr["tls"].(map[string]interface{}); ok && tls["enabled"].(bool) {
|
||||||
|
if reality, ok := tls["reality"].(map[string]interface{}); ok && reality["enabled"].(bool) {
|
||||||
|
params["security"] = "reality"
|
||||||
|
if pbk, ok := reality["public_key"].(string); ok {
|
||||||
|
params["pbk"] = pbk
|
||||||
|
}
|
||||||
|
if sid, ok := reality["short_id"].(string); ok {
|
||||||
|
params["sid"] = sid
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params["security"] = "tls"
|
||||||
|
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||||
|
params["allowInsecure"] = "1"
|
||||||
|
}
|
||||||
|
if flow, ok := userConfig["flow"].(string); ok {
|
||||||
|
params["flow"] = flow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sni, ok := tls["server_name"].(string); ok {
|
||||||
|
params["sni"] = sni
|
||||||
|
}
|
||||||
|
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||||
|
alpnList := make([]string, len(alpn))
|
||||||
|
for i, v := range alpn {
|
||||||
|
alpnList[i] = v.(string)
|
||||||
|
}
|
||||||
|
params["alpn"] = strings.Join(alpnList, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
port, _ := addr["server_port"].(float64)
|
||||||
|
uri := fmt.Sprintf("vless://%s@%s:%d", uuid, addr["server"].(string), uint(port))
|
||||||
|
uri = addParams(uri, params, addr["remark"].(string))
|
||||||
|
links = append(links, uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
func trojanLink(
|
||||||
|
userConfig map[string]interface{},
|
||||||
|
inbound map[string]interface{},
|
||||||
|
addrs []map[string]interface{}) []string {
|
||||||
|
password, _ := userConfig["password"].(string)
|
||||||
|
baseParams := getTransportParams(inbound["transport"])
|
||||||
|
var links []string
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
params := baseParams
|
||||||
|
if tls, ok := addr["tls"].(map[string]interface{}); ok && tls["enabled"].(bool) {
|
||||||
|
if reality, ok := tls["reality"].(map[string]interface{}); ok && reality["enabled"].(bool) {
|
||||||
|
params["security"] = "reality"
|
||||||
|
if pbk, ok := reality["public_key"].(string); ok {
|
||||||
|
params["pbk"] = pbk
|
||||||
|
}
|
||||||
|
if sid, ok := reality["short_id"].(string); ok {
|
||||||
|
params["sid"] = sid
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params["security"] = "tls"
|
||||||
|
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||||
|
params["allowInsecure"] = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sni, ok := tls["server_name"].(string); ok {
|
||||||
|
params["sni"] = sni
|
||||||
|
}
|
||||||
|
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||||
|
alpnList := make([]string, len(alpn))
|
||||||
|
for i, v := range alpn {
|
||||||
|
alpnList[i] = v.(string)
|
||||||
|
}
|
||||||
|
params["alpn"] = strings.Join(alpnList, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
port, _ := addr["server_port"].(float64)
|
||||||
|
uri := fmt.Sprintf("trojan://%s@%s:%d", password, addr["server"].(string), uint(port))
|
||||||
|
uri = addParams(uri, params, addr["remark"].(string))
|
||||||
|
links = append(links, uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
func vmessLink(
|
||||||
|
userConfig map[string]interface{},
|
||||||
|
inbound map[string]interface{},
|
||||||
|
addrs []map[string]interface{}) []string {
|
||||||
|
|
||||||
|
uuid, _ := userConfig["uuid"].(string)
|
||||||
|
trasportParams := getTransportParams(inbound["transport"])
|
||||||
|
var links []string
|
||||||
|
|
||||||
|
baseParams := map[string]interface{}{
|
||||||
|
"v": 2,
|
||||||
|
"id": uuid,
|
||||||
|
"aid": 0,
|
||||||
|
}
|
||||||
|
if trasportParams["type"] == "http" || trasportParams["type"] == "tcp" {
|
||||||
|
baseParams["net"] = "tcp"
|
||||||
|
if trasportParams["type"] == "http" {
|
||||||
|
baseParams["type"] = "http"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
baseParams["net"] = trasportParams["type"]
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
obj := baseParams
|
||||||
|
obj["addr"], _ = addr["server"].(string)
|
||||||
|
port, _ := addr["server_port"].(float64)
|
||||||
|
obj["port"] = uint(port)
|
||||||
|
obj["ps"], _ = addr["remark"].(string)
|
||||||
|
if trasportParams["host"] != "" {
|
||||||
|
obj["host"] = trasportParams["host"]
|
||||||
|
}
|
||||||
|
if trasportParams["path"] != "" {
|
||||||
|
obj["path"] = trasportParams["path"]
|
||||||
|
}
|
||||||
|
if tls, ok := addr["tls"].(map[string]interface{}); ok && tls["enabled"].(bool) {
|
||||||
|
obj["tls"] = "tls"
|
||||||
|
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||||
|
obj["allowInsecure"] = 1
|
||||||
|
}
|
||||||
|
if sni, ok := tls["server_name"].(string); ok {
|
||||||
|
obj["sni"] = sni
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
obj["tls"] = "none"
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonStr, _ := json.MarshalIndent(obj, "", " ")
|
||||||
|
|
||||||
|
uri := fmt.Sprintf("vmess://%s", toBase64(jsonStr))
|
||||||
|
links = append(links, uri)
|
||||||
|
}
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
func toBase64(d []byte) string {
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(d))
|
||||||
|
}
|
||||||
|
|
||||||
|
func addParams(uri string, params map[string]string, remark string) string {
|
||||||
|
URL, _ := url.Parse(uri)
|
||||||
|
q := URL.Query()
|
||||||
|
for k, v := range params {
|
||||||
|
q.Add(k, v)
|
||||||
|
}
|
||||||
|
URL.RawQuery = q.Encode()
|
||||||
|
URL.Fragment = remark
|
||||||
|
return URL.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTransportParams(t interface{}) map[string]string {
|
||||||
|
params := map[string]string{}
|
||||||
|
trasport, _ := t.(map[string]interface{})
|
||||||
|
if transportType, ok := trasport["type"].(string); ok {
|
||||||
|
params["type"] = transportType
|
||||||
|
} else {
|
||||||
|
params["type"] = "tcp"
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
switch params["type"] {
|
||||||
|
case "http":
|
||||||
|
if host, ok := trasport["host"].([]interface{}); ok {
|
||||||
|
var hosts []string
|
||||||
|
for _, v := range host {
|
||||||
|
hosts = append(hosts, v.(string))
|
||||||
|
}
|
||||||
|
params["host"] = strings.Join(hosts, ",")
|
||||||
|
}
|
||||||
|
if path, ok := trasport["path"].(string); ok {
|
||||||
|
params["path"] = path
|
||||||
|
}
|
||||||
|
case "ws":
|
||||||
|
if path, ok := trasport["path"].(string); ok {
|
||||||
|
params["path"] = path
|
||||||
|
}
|
||||||
|
if headers, ok := trasport["headers"].(map[string]interface{}); ok {
|
||||||
|
if host, ok := headers["Host"].(string); ok {
|
||||||
|
params["peer"] = host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "grpc":
|
||||||
|
if serviceName, ok := trasport["service_name"].(string); ok {
|
||||||
|
params["serviceName"] = serviceName
|
||||||
|
}
|
||||||
|
case "httpupgrade":
|
||||||
|
if host, ok := trasport["host"].(string); ok {
|
||||||
|
params["peer"] = host
|
||||||
|
}
|
||||||
|
if path, ok := trasport["path"].(string); ok {
|
||||||
|
params["path"] = path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
}
|
||||||
@@ -178,8 +178,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Link } from '@/plugins/link'
|
import { createClient, randomConfigs, updateConfigs, Link } from '@/types/clients'
|
||||||
import { createClient, randomConfigs, updateConfigs } from '@/types/clients'
|
|
||||||
import DatePick from '@/components/DateTime.vue'
|
import DatePick from '@/components/DateTime.vue'
|
||||||
import { HumanReadable } from '@/plugins/utils'
|
import { HumanReadable } from '@/plugins/utils'
|
||||||
|
|
||||||
@@ -225,7 +224,6 @@ export default {
|
|||||||
this.loading = true
|
this.loading = true
|
||||||
this.client.config = updateConfigs(this.clientConfig, this.client.name)
|
this.client.config = updateConfigs(this.clientConfig, this.client.name)
|
||||||
this.client.links = [
|
this.client.links = [
|
||||||
...this.links,
|
|
||||||
...this.extLinks.filter(l => l.uri != ''),
|
...this.extLinks.filter(l => l.uri != ''),
|
||||||
...this.subLinks.filter(l => l.uri != '')]
|
...this.subLinks.filter(l => l.uri != '')]
|
||||||
this.$emit('save', this.client, this.clientStats)
|
this.$emit('save', this.client, this.clientStats)
|
||||||
|
|||||||
@@ -1,465 +0,0 @@
|
|||||||
import { Hysteria, Hysteria2, InTypes, Inbound, Naive, Shadowsocks, TUIC, Trojan, VLESS, VMess } from "@/types/inbounds"
|
|
||||||
import { HTTP, WebSocket, gRPC, HTTPUpgrade, Transport, TrspTypes } from "@/types/transport"
|
|
||||||
import RandomUtil from "./randomUtil"
|
|
||||||
import { Client } from "@/types/clients"
|
|
||||||
|
|
||||||
export interface Link {
|
|
||||||
type: "local" | "external" | "sub"
|
|
||||||
remark?: string
|
|
||||||
uri: string
|
|
||||||
}
|
|
||||||
|
|
||||||
function utf8ToBase64(utf8String: string): string {
|
|
||||||
const encodedUtf8 = encodeURIComponent(utf8String).replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)))
|
|
||||||
return btoa(encodedUtf8)
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace LinkUtil {
|
|
||||||
export function linkGenerator(user: Client, inbound: Inbound, tls: any = {}, addrs: any[] = []): string[] {
|
|
||||||
switch(inbound.type){
|
|
||||||
case InTypes.Shadowsocks:
|
|
||||||
return shadowsocksLink(user,<Shadowsocks>inbound, addrs)
|
|
||||||
case InTypes.Naive:
|
|
||||||
return naiveLink(user,<Naive>inbound, addrs, tls)
|
|
||||||
case InTypes.Hysteria:
|
|
||||||
return hysteriaLink(user,<Hysteria>inbound, addrs, tls)
|
|
||||||
case InTypes.Hysteria2:
|
|
||||||
return hysteria2Link(user,<Hysteria2>inbound, addrs, tls)
|
|
||||||
case InTypes.TUIC:
|
|
||||||
return tuicLink(user,<TUIC>inbound, addrs, tls)
|
|
||||||
case InTypes.VLESS:
|
|
||||||
return vlessLink(user,<VLESS>inbound, addrs, tls)
|
|
||||||
case InTypes.Trojan:
|
|
||||||
return trojanLink(user,<Trojan>inbound, addrs, tls)
|
|
||||||
case InTypes.VMess:
|
|
||||||
return vmessLink(user,<VMess>inbound, addrs, tls)
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
function shadowsocksLink(user: Client, inbound: Shadowsocks, addrs: any[]): string[] {
|
|
||||||
const userPass = inbound.method == "2022-blake3-aes-128-gcm" ? user.config.shadowsocks16?.password : user.config.shadowsocks?.password
|
|
||||||
const password = [userPass]
|
|
||||||
if (inbound.method.startsWith('2022')) password.push(inbound.password)
|
|
||||||
const params = {
|
|
||||||
tfo: inbound.tcp_fast_open? 1 : null,
|
|
||||||
network: inbound.network?? null
|
|
||||||
}
|
|
||||||
|
|
||||||
let links = <string[]>[]
|
|
||||||
if (addrs.length == 0) {
|
|
||||||
const uri = new URL(`ss://${utf8ToBase64(inbound.method + ':' + password.join(':'))}@${location.hostname}:${inbound.listen_port}`)
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
} else {
|
|
||||||
addrs.forEach(a => {
|
|
||||||
const uri = new URL(`ss://${utf8ToBase64(inbound.method + ':' + password.join(':'))}@${a.server}:${a.server_port}`)
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(a.remark ? inbound.tag + a.remark : inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
function hysteriaLink(user: Client, inbound: Hysteria, addrs: any[], tls: any): string[] {
|
|
||||||
const auth = user.config.hysteria.auth_str
|
|
||||||
const params = {
|
|
||||||
upmbps: inbound.up_mbps?? null,
|
|
||||||
downmbps: inbound.down_mbps?? null,
|
|
||||||
auth: auth?? null,
|
|
||||||
peer: tls?.server?.server_name?? null,
|
|
||||||
alpn: tls?.server?.alpn?.join(',')?? null,
|
|
||||||
obfsParam: inbound.obfs?? null,
|
|
||||||
fastopen: inbound.tcp_fast_open? 1 : 0,
|
|
||||||
insecure: tls?.client?.insecure ? 1 : null
|
|
||||||
}
|
|
||||||
|
|
||||||
let links = <string[]>[]
|
|
||||||
if (addrs.length == 0) {
|
|
||||||
const uri = new URL(`hysteria://${location.hostname}:${inbound.listen_port}`)
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
} else {
|
|
||||||
addrs.forEach(a => {
|
|
||||||
const uri = new URL(`hysteria://${a.server}:${a.server_port}`)
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a.server_name?.length>0) {
|
|
||||||
uri.searchParams.set('peer', a.server_name)
|
|
||||||
} else {
|
|
||||||
tls?.server?.server_name ? uri.searchParams.set('peer', tls?.server?.server_name) : uri.searchParams.delete('peer')
|
|
||||||
}
|
|
||||||
if (a.insecure) {
|
|
||||||
uri.searchParams.set('insecure', '1')
|
|
||||||
} else {
|
|
||||||
tls?.client?.insecure ? uri.searchParams.set('insecure', '1') : uri.searchParams.delete('insecure')
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(a.remark ? inbound.tag + a.remark : inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
function hysteria2Link(user: Client, inbound: Hysteria2, addrs: any[], tls: any): string[] {
|
|
||||||
const password = user.config.hysteria2.password
|
|
||||||
const params = {
|
|
||||||
upmbps: inbound.up_mbps?? null,
|
|
||||||
downmbps: inbound.down_mbps?? null,
|
|
||||||
sni: tls?.server?.server_name?? null,
|
|
||||||
alpn: tls?.server?.alpn?.join(',')?? null,
|
|
||||||
obfs: inbound.obfs?.type?? null,
|
|
||||||
'obfs-password': inbound.obfs?.password?? null,
|
|
||||||
fastopen: inbound.tcp_fast_open? 1 : 0,
|
|
||||||
insecure: tls?.client?.insecure ? 1 : null
|
|
||||||
}
|
|
||||||
|
|
||||||
let links = <string[]>[]
|
|
||||||
if (addrs.length == 0) {
|
|
||||||
const uri = new URL(`hysteria2://${password}@${location.hostname}:${inbound.listen_port}`)
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
} else {
|
|
||||||
addrs.forEach(a => {
|
|
||||||
const uri = new URL(`hysteria2://${password}@${a.server}:${a.server_port}`)
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a.server_name?.length>0) {
|
|
||||||
uri.searchParams.set('sni', a.server_name)
|
|
||||||
} else {
|
|
||||||
tls?.server?.server_name ? uri.searchParams.set('sni', tls?.server?.server_name) : uri.searchParams.delete('sni')
|
|
||||||
}
|
|
||||||
if (a.insecure) {
|
|
||||||
uri.searchParams.set('insecure', '1')
|
|
||||||
} else {
|
|
||||||
tls?.client?.insecure ? uri.searchParams.set('insecure', '1') : uri.searchParams.delete('insecure')
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(a.remark ? inbound.tag + a.remark : inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
function naiveLink(user: Client, inbound: Naive, addrs: any[], tls: any): string[] {
|
|
||||||
const password = user.config.naive.password
|
|
||||||
|
|
||||||
let links = <string[]>[]
|
|
||||||
if (addrs.length == 0) {
|
|
||||||
const params = {
|
|
||||||
padding: 1,
|
|
||||||
peer: tls?.server?.server_name?? null,
|
|
||||||
alpn: tls?.server?.alpn?.join(',')?? null,
|
|
||||||
tfo: inbound.tcp_fast_open? 1 : 0,
|
|
||||||
allowInsecure: tls?.client?.insecure ? 1 : null
|
|
||||||
}
|
|
||||||
const uri = `http2://${utf8ToBase64(user.name + ":" + password + "@" + location.hostname + ":" + inbound.listen_port)}`
|
|
||||||
const paramsArray = []
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
paramsArray.push(`${key}=${encodeURIComponent(value.toString())}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
links.push(uri.toString() + "?" + paramsArray.join('&') + "#" + inbound.tag)
|
|
||||||
} else {
|
|
||||||
addrs.forEach(a => {
|
|
||||||
const params = {
|
|
||||||
padding: 1,
|
|
||||||
peer: a.server_name?.length>0 ? a.server_name : tls?.server?.server_name?? null,
|
|
||||||
alpn: tls?.server?.alpn?.join(',')?? null,
|
|
||||||
tfo: inbound.tcp_fast_open? 1 : 0,
|
|
||||||
allowInsecure: a.insecure ? 1 : tls?.client?.insecure ? 1 : null
|
|
||||||
}
|
|
||||||
const uri = `http2://${utf8ToBase64(user + ":" + password + "@" + a.server + ":" + a.server_port)}`
|
|
||||||
const paramsArray = []
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
paramsArray.push(`${key}=${encodeURIComponent(value.toString())}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
links.push(uri.toString() + "?" + paramsArray.join('&') + "#" + encodeURIComponent(a.remark ? inbound.tag + a.remark : inbound.tag))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
function tuicLink(user: Client, inbound: TUIC, addrs: any[], tls: any): string[] {
|
|
||||||
const u = user.config.tuic
|
|
||||||
const params = {
|
|
||||||
sni: tls?.server?.server_name?? null,
|
|
||||||
alpn: tls?.server?.alpn?.join(',')?? null,
|
|
||||||
congestion_control: inbound.congestion_control?? null,
|
|
||||||
allowInsecure: tls?.client?.insecure ? 1 : null,
|
|
||||||
disable_sni: tls?.client?.disable_sni ? 1 : null
|
|
||||||
}
|
|
||||||
|
|
||||||
let links = <string[]>[]
|
|
||||||
if (addrs.length == 0) {
|
|
||||||
const uri = new URL(`tuic://${u?.uuid}:${u?.password}@${location.hostname}:${inbound.listen_port}`)
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
} else {
|
|
||||||
addrs.forEach(a => {
|
|
||||||
const uri = new URL(`tuic://${u?.uuid}:${u?.password}@${a.server}:${a.server_port}`)
|
|
||||||
for (const [key, value] of Object.entries(params)){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a.server_name?.length>0) {
|
|
||||||
uri.searchParams.set('sni', a.server_name)
|
|
||||||
} else {
|
|
||||||
tls?.server?.server_name ? uri.searchParams.set('sni', tls?.server?.server_name) : uri.searchParams.delete('sni')
|
|
||||||
}
|
|
||||||
if (a.insecure) {
|
|
||||||
uri.searchParams.set('allowInsecure', '1')
|
|
||||||
} else {
|
|
||||||
tls?.client?.insecure ? uri.searchParams.set('allowInsecure', '1') : uri.searchParams.delete('allowInsecure')
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(a.remark ? inbound.tag + a.remark : inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTransportParams(t:Transport): any {
|
|
||||||
if (Object.keys(t).length == 0) return {}
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
host: <string|null>'',
|
|
||||||
path: <string|null>'',
|
|
||||||
serviceName: <string|null>'',
|
|
||||||
}
|
|
||||||
switch (t.type){
|
|
||||||
case TrspTypes.HTTP:
|
|
||||||
const th = <HTTP>t
|
|
||||||
params.host = th.host?.join(',')?? null
|
|
||||||
params.path = th.path?? null
|
|
||||||
break
|
|
||||||
case TrspTypes.WebSocket:
|
|
||||||
const tw = <WebSocket>t
|
|
||||||
params.path = tw.path?? null
|
|
||||||
params.host = tw.headers?.Host?? null
|
|
||||||
break
|
|
||||||
case TrspTypes.gRPC:
|
|
||||||
const tg = <gRPC>t
|
|
||||||
params.serviceName = tg.service_name?? null
|
|
||||||
break
|
|
||||||
case TrspTypes.HTTPUpgrade:
|
|
||||||
const tu = <HTTPUpgrade>t
|
|
||||||
params.host = tu.host?? null
|
|
||||||
params.path = tu.path?? null
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return params
|
|
||||||
}
|
|
||||||
|
|
||||||
function vlessLink(user: Client, inbound: VLESS, addrs: any[], tls: any): string[] {
|
|
||||||
const u = user.config.vless
|
|
||||||
const transport = <Transport>inbound.transport
|
|
||||||
|
|
||||||
const tParams = getTransportParams(transport)
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
type: transport?.type?? 'tcp',
|
|
||||||
security: tls?.server?.enabled? tls?.server?.reality?.enabled ? 'reality' : 'tls' : null,
|
|
||||||
alpn: tls?.server?.alpn?.join(',')?? null,
|
|
||||||
sni: tls?.server?.server_name?? null,
|
|
||||||
flow: tls?.server?.enabled ? u?.flow?? null : null,
|
|
||||||
allowInsecure: tls?.client?.insecure ? 1 : null,
|
|
||||||
fp: tls?.client?.utls?.enabled ? tls.client.utls.fingerprint : null,
|
|
||||||
pbk: tls?.client?.reality?.public_key?? null,
|
|
||||||
sid: tls?.server?.reality?.enabled ? (tls?.server?.reality?.short_id?.length>0 ? tls.server.reality.short_id[RandomUtil.randomInt(tls.server.reality.short_id.length)] : null) : null
|
|
||||||
}
|
|
||||||
let links = <string[]>[]
|
|
||||||
if (addrs.length == 0) {
|
|
||||||
const uri = new URL(`vless://${u?.uuid}@${location.hostname}:${inbound.listen_port}`)
|
|
||||||
for (const [key, value] of Object.entries({...params, ...tParams})){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
} else {
|
|
||||||
addrs.forEach(a => {
|
|
||||||
const uri = new URL(`vless://${u?.uuid}@${a.server}:${a.server_port}`)
|
|
||||||
for (const [key, value] of Object.entries({...params, ...tParams})){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a.tls != undefined){
|
|
||||||
if (a.tls) {
|
|
||||||
uri.searchParams.set('security','tls')
|
|
||||||
} else {
|
|
||||||
uri.searchParams.delete('security')
|
|
||||||
uri.searchParams.delete('sni')
|
|
||||||
uri.searchParams.delete('alpn')
|
|
||||||
uri.searchParams.delete('allowInsecure')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a.server_name?.length>0) {
|
|
||||||
uri.searchParams.set('sni', a.server_name)
|
|
||||||
} else {
|
|
||||||
tls?.server?.server_name ? uri.searchParams.set('sni', tls?.server?.server_name) : uri.searchParams.delete('sni')
|
|
||||||
}
|
|
||||||
if (a.insecure) {
|
|
||||||
uri.searchParams.set('allowInsecure', '1')
|
|
||||||
} else {
|
|
||||||
tls?.client?.insecure ? uri.searchParams.set('allowInsecure', '1') : uri.searchParams.delete('allowInsecure')
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(a.remark ? inbound.tag + a.remark : inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
function trojanLink(user: Client, inbound: Trojan, addrs: any[], tls: any): string[] {
|
|
||||||
const u = user.config.trojan
|
|
||||||
const transport = <Transport>inbound.transport
|
|
||||||
|
|
||||||
const tParams = getTransportParams(transport)
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
type: transport?.type?? 'tcp',
|
|
||||||
security: tls?.server?.enabled? tls?.server?.reality?.enabled ? 'reality' : 'tls' : null,
|
|
||||||
alpn: tls?.server?.alpn?.join(',')?? null,
|
|
||||||
sni: tls?.server?.server_name?? null,
|
|
||||||
allowInsecure: tls?.client?.insecure ? 1 : null,
|
|
||||||
fp: tls?.client?.utls?.enabled ? tls.client.utls.fingerprint : null,
|
|
||||||
pbk: tls?.client?.reality?.public_key?? null,
|
|
||||||
sid: tls?.server?.reality?.enabled ? (tls?.server?.reality?.short_id?.length>0 ? tls?.server?.reality.short_id[RandomUtil.randomInt(tls?.server?.reality.short_id.length)] : null) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
let links = <string[]>[]
|
|
||||||
if (addrs.length == 0) {
|
|
||||||
const uri = new URL(`trojan://${u?.password}@${location.hostname}:${inbound.listen_port}`)
|
|
||||||
for (const [key, value] of Object.entries({...params, ...tParams})){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
} else {
|
|
||||||
addrs.forEach(a => {
|
|
||||||
const uri = new URL(`trojan://${u?.password}@${a.server}:${a.server_port}`)
|
|
||||||
for (const [key, value] of Object.entries({...params, ...tParams})){
|
|
||||||
if (value) {
|
|
||||||
uri.searchParams.set(key, value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a.tls != undefined){
|
|
||||||
if (a.tls) {
|
|
||||||
uri.searchParams.set('security','tls')
|
|
||||||
} else {
|
|
||||||
uri.searchParams.delete('security')
|
|
||||||
uri.searchParams.delete('sni')
|
|
||||||
uri.searchParams.delete('alpn')
|
|
||||||
uri.searchParams.delete('allowInsecure')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a.server_name?.length>0) {
|
|
||||||
uri.searchParams.set('sni', a.server_name)
|
|
||||||
} else {
|
|
||||||
tls?.server?.server_name ? uri.searchParams.set('sni', tls?.server?.server_name) : uri.searchParams.delete('sni')
|
|
||||||
}
|
|
||||||
if (a.insecure) {
|
|
||||||
uri.searchParams.set('allowInsecure', '1')
|
|
||||||
} else {
|
|
||||||
tls?.client?.insecure ? uri.searchParams.set('allowInsecure', '1') : uri.searchParams.delete('allowInsecure')
|
|
||||||
}
|
|
||||||
uri.hash = encodeURIComponent(a.remark ? inbound.tag + a.remark : inbound.tag)
|
|
||||||
links.push(uri.toString())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
function vmessLink(user: Client, inbound: VMess, addrs: any[], tls: any): string[] {
|
|
||||||
const u = user.config.vmess
|
|
||||||
const transport = <Transport>inbound.transport
|
|
||||||
|
|
||||||
const tParams = getTransportParams(transport)
|
|
||||||
if (transport.type == TrspTypes.gRPC) tParams.path = tParams.serviceName
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
v: 2,
|
|
||||||
add: location.hostname,
|
|
||||||
aid: u?.alterId,
|
|
||||||
host: tParams.host?? undefined,
|
|
||||||
id: u?.uuid,
|
|
||||||
net: transport?.type == undefined || transport?.type == 'http' ? 'tcp' : transport.type,
|
|
||||||
type: transport?.type == 'http' ? 'http' : undefined,
|
|
||||||
path: tParams.path?? undefined,
|
|
||||||
port: inbound.listen_port,
|
|
||||||
ps: inbound.tag,
|
|
||||||
sni: tls?.server?.server_name?? undefined,
|
|
||||||
tls: tls?.server && Object.keys(tls.server).length>0? 'tls' : 'none',
|
|
||||||
allowInsecure: tls?.client?.insecure ? 1 : undefined
|
|
||||||
}
|
|
||||||
let links = <string[]>[]
|
|
||||||
if (addrs.length == 0) {
|
|
||||||
links.push('vmess://' + utf8ToBase64(JSON.stringify(params, null, 2)))
|
|
||||||
} else {
|
|
||||||
addrs.forEach(a => {
|
|
||||||
let newParams = {...params}
|
|
||||||
newParams.add = a.server
|
|
||||||
newParams.port = a.server_port
|
|
||||||
if (a.tls != undefined){
|
|
||||||
if (a.tls) {
|
|
||||||
newParams.tls = 'tls'
|
|
||||||
} else {
|
|
||||||
newParams.tls = 'none'
|
|
||||||
delete newParams.sni
|
|
||||||
delete newParams.allowInsecure
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a.server_name?.length>0) {
|
|
||||||
newParams.sni = a.server_name
|
|
||||||
}
|
|
||||||
if (a.insecure) {
|
|
||||||
newParams.allowInsecure = 1
|
|
||||||
}
|
|
||||||
newParams.ps = inbound.tag + (a.remark??'')
|
|
||||||
links.push('vmess://' + utf8ToBase64(JSON.stringify(newParams, null, 2)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -60,9 +60,8 @@ const Data = defineStore('Data', {
|
|||||||
let postData = {
|
let postData = {
|
||||||
object: object,
|
object: object,
|
||||||
action: action,
|
action: action,
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data, null, 2),
|
||||||
userLinks: userLinks == null ? undefined : JSON.stringify(userLinks),
|
userLinks: userLinks == null ? undefined : JSON.stringify(userLinks),
|
||||||
outJsons: outJsons == null ? undefined : JSON.stringify(outJsons),
|
|
||||||
}
|
}
|
||||||
if (userLinks == null) {
|
if (userLinks == null) {
|
||||||
delete postData.userLinks
|
delete postData.userLinks
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import { Link } from "@/plugins/link"
|
|
||||||
import RandomUtil from "@/plugins/randomUtil"
|
import RandomUtil from "@/plugins/randomUtil"
|
||||||
|
|
||||||
|
export interface Link {
|
||||||
|
type: "local" | "external" | "sub"
|
||||||
|
remark?: string
|
||||||
|
uri: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface Client {
|
export interface Client {
|
||||||
id?: number
|
id?: number
|
||||||
enable: boolean
|
enable: boolean
|
||||||
|
|||||||
@@ -345,10 +345,9 @@ import ClientModal from '@/layouts/modals/Client.vue'
|
|||||||
import ClientBulk from '@/layouts/modals/ClientBulk.vue'
|
import ClientBulk from '@/layouts/modals/ClientBulk.vue'
|
||||||
import QrCode from '@/layouts/modals/QrCode.vue'
|
import QrCode from '@/layouts/modals/QrCode.vue'
|
||||||
import Stats from '@/layouts/modals/Stats.vue'
|
import Stats from '@/layouts/modals/Stats.vue'
|
||||||
import { Client, createClient } from '@/types/clients'
|
import { Client } from '@/types/clients'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { Inbound, inboundWithUsers } from '@/types/inbounds'
|
import { Inbound, inboundWithUsers } from '@/types/inbounds'
|
||||||
import { Link, LinkUtil } from '@/plugins/link'
|
|
||||||
import { HumanReadable } from '@/plugins/utils'
|
import { HumanReadable } from '@/plugins/utils'
|
||||||
import { i18n } from '@/locales'
|
import { i18n } from '@/locales'
|
||||||
import { push } from 'notivue'
|
import { push } from 'notivue'
|
||||||
@@ -443,31 +442,11 @@ const saveModal = async (data:any) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild links
|
|
||||||
const clientInbounds = data.inbounds.length == 0 ? [] : await Data().loadInbounds(data.inbounds)
|
|
||||||
data.links = updateLinks(data, clientInbounds)
|
|
||||||
|
|
||||||
// save data
|
// save data
|
||||||
const success = await Data().save("clients", modal.value.id == 0 ? "new" : "edit", data)
|
const success = await Data().save("clients", modal.value.id == 0 ? "new" : "edit", data)
|
||||||
if (success) modal.value.visible = false
|
if (success) modal.value.visible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateLinks = (c:Client, clientInbounds:Inbound[]):Link[] => {
|
|
||||||
const newLinks = <Link[]>[]
|
|
||||||
clientInbounds.forEach(i =>{
|
|
||||||
const tls = i.tls_id && i.tls_id>0 ? Data().tlsConfigs?.findLast((t:any) => t.id == i.tls_id) : undefined
|
|
||||||
const uris = LinkUtil.linkGenerator(c,i, tls, i.addrs)
|
|
||||||
if (uris.length>0){
|
|
||||||
uris.forEach(uri => {
|
|
||||||
newLinks.push(<Link>{ type: 'local', remark: i.tag, uri: uri })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let links = c.links && c.links.length>0? c.links : <Link[]>[]
|
|
||||||
links = [...newLinks, ...links.filter(l => l.type != 'local')]
|
|
||||||
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
const delClient = async (id: number) => {
|
const delClient = async (id: number) => {
|
||||||
const index = clients.value.findIndex(c => c.id === id)
|
const index = clients.value.findIndex(c => c.id === id)
|
||||||
const success = await Data().save("clients", "del", id)
|
const success = await Data().save("clients", "del", id)
|
||||||
@@ -557,10 +536,6 @@ const closeBulk = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const saveBulk = async (bulkClients: Client[], clientInbounds: number[]) => {
|
const saveBulk = async (bulkClients: Client[], clientInbounds: number[]) => {
|
||||||
const inboundData = clientInbounds.length == 0 ? [] : await Data().loadInbounds(clientInbounds)
|
|
||||||
bulkClients.forEach((c,c_index) => {
|
|
||||||
bulkClients[c_index].links = updateLinks(c, inboundData)
|
|
||||||
})
|
|
||||||
clients.value.push(...bulkClients)
|
clients.value.push(...bulkClients)
|
||||||
closeBulk()
|
closeBulk()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ import { Config } from '@/types/config'
|
|||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { Inbound, inboundWithUsers } from '@/types/inbounds'
|
import { Inbound, inboundWithUsers } from '@/types/inbounds'
|
||||||
import { Client } from '@/types/clients'
|
import { Client } from '@/types/clients'
|
||||||
import { Link, LinkUtil } from '@/plugins/link'
|
|
||||||
import { i18n } from '@/locales'
|
import { i18n } from '@/locales'
|
||||||
import { push } from 'notivue'
|
import { push } from 'notivue'
|
||||||
|
|
||||||
@@ -168,67 +167,16 @@ const saveModal = async (data:Inbound) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let userLinkDiff = []
|
|
||||||
// Update links
|
|
||||||
if (data.id > 0 && oldInbound != null) {
|
|
||||||
userLinkDiff = updateLinks(data,oldInbound)
|
|
||||||
}
|
|
||||||
|
|
||||||
// save data
|
// save data
|
||||||
const success = await Data().save("inbounds", modal.value.id == 0 ? "new" : "edit", data, userLinkDiff)
|
const success = await Data().save("inbounds", modal.value.id == 0 ? "new" : "edit", data)
|
||||||
if (success) modal.value.visible = false
|
if (success) modal.value.visible = false
|
||||||
}
|
}
|
||||||
const updateLinks = (i: Inbound, o: Inbound): any[] => {
|
|
||||||
let diff = <any[]>[]
|
|
||||||
const uClients = clients.value.filter(c => c.inbounds.includes(i.id))
|
|
||||||
if (uClients.length == 0) return diff
|
|
||||||
|
|
||||||
if (inboundWithUsers.includes(o.type) && !inboundWithUsers.includes(i.type)){
|
|
||||||
// Remove old inbound links if new type does not support users
|
|
||||||
uClients.forEach((u:Client) => {
|
|
||||||
u.inbounds = u.inbounds.filter(i => i != o.id)
|
|
||||||
const otherLocalLinks = u.links.filter(l => l.type == 'local' && l.remark != o.tag)
|
|
||||||
let links = u.links && u.links.length>0? u.links : <Link[]>[]
|
|
||||||
links = [...otherLocalLinks, ...links.filter(l => l.type != 'local')]
|
|
||||||
|
|
||||||
diff.push({ id: u.id, links: links, inbounds: u.inbounds })
|
|
||||||
})
|
|
||||||
} else if(inboundWithUsers.includes(i.type)){
|
|
||||||
// Add new inbound links if new type supports users
|
|
||||||
const tls = tlsConfigs?.value.findLast((t:any) => t.id == i.tls_id)
|
|
||||||
uClients.forEach((u:Client) => {
|
|
||||||
const otherLocalLinks = u.links.filter(l => l.type == 'local' && l.remark != i.tag)
|
|
||||||
const uris = LinkUtil.linkGenerator(u,i, tls, i.addrs)
|
|
||||||
let newLinks = <Link[]>[]
|
|
||||||
if (uris.length>0){
|
|
||||||
uris.forEach(uri => {
|
|
||||||
newLinks.push(<Link>{ type: 'local', remark: i.tag, uri: uri })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
let links = u.links && u.links.length>0? u.links : <Link[]>[]
|
|
||||||
links = [...otherLocalLinks, ...newLinks, ...links.filter(l => l.type != 'local')]
|
|
||||||
|
|
||||||
diff.push({ id: u.id, links: links, inbounds: u.inbounds })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return diff
|
|
||||||
}
|
|
||||||
const delInbound = async (id: number) => {
|
const delInbound = async (id: number) => {
|
||||||
const index = inbounds.value.findIndex(i => i.id == id)
|
const index = inbounds.value.findIndex(i => i.id == id)
|
||||||
const inb = inbounds.value[index]
|
const tag = inbounds.value[index].tag
|
||||||
const tag = inb.tag
|
|
||||||
|
|
||||||
let diff = <any[]>[]
|
const success = await Data().save("inbounds", "del", tag)
|
||||||
// delete inbound in client table
|
|
||||||
const inboundClients = clients.value.filter(c => c.inbounds.includes(id))
|
|
||||||
inboundClients.forEach((c:Client) => {
|
|
||||||
c.inbounds = c.inbounds.filter((x:number) => x!=id)
|
|
||||||
c.links = c.links.filter((x:any) => x.remark!=tag)
|
|
||||||
diff.push({ id: c.id, links: c.links, inbounds: c.inbounds })
|
|
||||||
})
|
|
||||||
|
|
||||||
const success = await Data().save("inbounds", "del", tag, diff)
|
|
||||||
if (success) delOverlay.value[index] = false
|
if (success) delOverlay.value[index] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,29 +132,8 @@ const clone = (obj: any) => {
|
|||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
modal.value.visible = false
|
modal.value.visible = false
|
||||||
}
|
}
|
||||||
const saveModal = async (data:any) => {
|
const saveModal = async (data:tls) => {
|
||||||
let userLinks = <any[]>[]
|
const success = await Data().save("tls", data.id == 0 ? "new" : "edit", data)
|
||||||
// New or Edit
|
|
||||||
if (modal.value.id > 0) {
|
|
||||||
const inboundIds = inbounds.value.filter(i => i.tls_id == modal.value.id).map(i => i.id)
|
|
||||||
if (inboundIds.length > 0) {
|
|
||||||
const tlsInbounds = inboundIds.length == 0 ? [] : await Data().loadInbounds(inboundIds)
|
|
||||||
for (const inbound of tlsInbounds) {
|
|
||||||
// Update links
|
|
||||||
const diff = updateLinks(inbound)
|
|
||||||
diff.forEach((d: any) => {
|
|
||||||
if (userLinks.findIndex(l => l.id == d.id) == -1) {
|
|
||||||
userLinks.push(d)
|
|
||||||
} else {
|
|
||||||
const index = userLinks.findIndex(l => l.id == d.id)
|
|
||||||
userLinks[index].links = d.links
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
const success = await Data().save("tls", data.id == 0 ? "new" : "edit", data, userLinks.length > 0 ? null: userLinks)
|
|
||||||
if (success) modal.value.visible = false
|
if (success) modal.value.visible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,29 +143,4 @@ const delTls = async (id: number) => {
|
|||||||
if (success) delOverlay.value[index] = false
|
if (success) delOverlay.value[index] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateLinks = (i: Inbound): any[] => {
|
|
||||||
let diff = <any[]>[]
|
|
||||||
if(inboundWithUsers.includes(i.type) && i.id != 0){
|
|
||||||
const uClients = clients.value.filter(c => c.inbounds.includes(i.id))
|
|
||||||
const tlsClient = tlsConfigs?.value.findLast((t:any) => t.id == i.tls_id)
|
|
||||||
uClients.forEach((u:Client) => {
|
|
||||||
const otherLocalLinks = u.links.filter(l => l.type == 'local' && l.remark != i.tag)
|
|
||||||
const uris = LinkUtil.linkGenerator(u,i, tlsClient, i.addrs)
|
|
||||||
let newLinks = <Link[]>[]
|
|
||||||
if (uris.length>0){
|
|
||||||
uris.forEach(uri => {
|
|
||||||
newLinks.push(<Link>{ type: 'local', remark: i.tag, uri: uri })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
let links = u.links && u.links.length>0? u.links : <Link[]>[]
|
|
||||||
links = [...otherLocalLinks, ...newLinks, ...links.filter(l => l.type != 'local')]
|
|
||||||
|
|
||||||
u.links = links
|
|
||||||
diff.push({ id: u.id, links: links })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return diff
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user