init users on create inbound #411
This commit is contained in:
+2
-1
@@ -88,7 +88,8 @@ 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")
|
||||||
objs, err := a.ConfigService.Save(obj, act, json.RawMessage(data), loginUser, hostname)
|
initUsers := c.Request.FormValue("initUsers")
|
||||||
|
objs, err := a.ConfigService.Save(obj, act, json.RawMessage(data), initUsers, loginUser, hostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "save", err)
|
jsonMsg(c, "save", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"s-ui/logger"
|
"s-ui/logger"
|
||||||
"s-ui/util"
|
"s-ui/util"
|
||||||
"s-ui/util/common"
|
"s-ui/util/common"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -156,6 +157,56 @@ func (s *ClientService) updateLinksWithFixedInbounds(tx *gorm.DB, clients []*mod
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ClientService) UpdateClientsOnInboundAdd(tx *gorm.DB, initIds string, inboundId uint, hostname string) error {
|
||||||
|
clientIds := strings.Split(initIds, ",")
|
||||||
|
var clients []model.Client
|
||||||
|
err := tx.Model(model.Client{}).Where("id in ?", clientIds).Find(&clients).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var inbound model.Inbound
|
||||||
|
err = tx.Model(model.Inbound{}).Preload("Tls").Where("id = ?", inboundId).Find(&inbound).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, client := range clients {
|
||||||
|
// Add inbounds
|
||||||
|
var clientInbounds []uint
|
||||||
|
json.Unmarshal(client.Inbounds, &clientInbounds)
|
||||||
|
clientInbounds = append(clientInbounds, inboundId)
|
||||||
|
client.Inbounds, err = json.MarshalIndent(clientInbounds, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Add links
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ClientService) UpdateClientsOnInboundDelete(tx *gorm.DB, id uint, tag string) error {
|
func (s *ClientService) UpdateClientsOnInboundDelete(tx *gorm.DB, id uint, tag string) error {
|
||||||
var clients []model.Client
|
var clients []model.Client
|
||||||
err := tx.Table("clients").
|
err := tx.Table("clients").
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ func (s *ConfigService) StopCore() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConfigService) Save(obj string, act string, data json.RawMessage, loginUser string, hostname string) ([]string, error) {
|
func (s *ConfigService) Save(obj string, act string, data json.RawMessage, initUsers string, loginUser string, hostname string) ([]string, error) {
|
||||||
var err error
|
var err error
|
||||||
var inboundIds []uint
|
var inboundIds []uint
|
||||||
var inboundId uint
|
var inboundId uint
|
||||||
@@ -139,7 +139,7 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, login
|
|||||||
case "tls":
|
case "tls":
|
||||||
inboundIds, err = s.TlsService.Save(tx, act, data)
|
inboundIds, err = s.TlsService.Save(tx, act, data)
|
||||||
case "inbounds":
|
case "inbounds":
|
||||||
inboundId, err = s.InboundService.Save(tx, act, data, hostname)
|
inboundId, err = s.InboundService.Save(tx, act, data, initUsers, hostname)
|
||||||
case "outbounds":
|
case "outbounds":
|
||||||
err = s.OutboundService.Save(tx, act, data)
|
err = s.OutboundService.Save(tx, act, data)
|
||||||
case "endpoints":
|
case "endpoints":
|
||||||
@@ -173,7 +173,6 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, login
|
|||||||
// Commit changes so far
|
// Commit changes so far
|
||||||
tx.Commit()
|
tx.Commit()
|
||||||
LastUpdate = time.Now().Unix()
|
LastUpdate = time.Now().Unix()
|
||||||
var objs []string = []string{obj}
|
|
||||||
tx = db.Begin()
|
tx = db.Begin()
|
||||||
|
|
||||||
// Update side changes
|
// Update side changes
|
||||||
@@ -186,8 +185,10 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, login
|
|||||||
}
|
}
|
||||||
objs = append(objs, "clients")
|
objs = append(objs, "clients")
|
||||||
}
|
}
|
||||||
if obj == "inbounds" && act != "add" {
|
if obj == "inbounds" {
|
||||||
switch act {
|
switch act {
|
||||||
|
case "new":
|
||||||
|
err = s.ClientService.UpdateClientsOnInboundAdd(tx, initUsers, inboundId, hostname)
|
||||||
case "edit":
|
case "edit":
|
||||||
err = s.ClientService.UpdateLinksByInboundChange(tx, []uint{inboundId}, hostname)
|
err = s.ClientService.UpdateLinksByInboundChange(tx, []uint{inboundId}, hostname)
|
||||||
case "del":
|
case "del":
|
||||||
|
|||||||
+67
-14
@@ -96,7 +96,7 @@ func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error) {
|
|||||||
return inbounds, nil
|
return inbounds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, hostname string) (uint, error) {
|
func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, initUsers string, hostname string) (uint, error) {
|
||||||
var err error
|
var err error
|
||||||
var id uint
|
var id uint
|
||||||
|
|
||||||
@@ -107,7 +107,6 @@ func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, hos
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
id = inbound.Id
|
|
||||||
if inbound.TlsId > 0 {
|
if inbound.TlsId > 0 {
|
||||||
err = tx.Model(model.Tls{}).Where("id = ?", inbound.TlsId).Find(&inbound.Tls).Error
|
err = tx.Model(model.Tls{}).Where("id = ?", inbound.TlsId).Find(&inbound.Tls).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -115,6 +114,17 @@ func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, hos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = util.FillOutJson(&inbound, hostname)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Save(&inbound).Error
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
id = inbound.Id
|
||||||
|
|
||||||
if corePtr.IsRunning() {
|
if corePtr.IsRunning() {
|
||||||
if act == "edit" {
|
if act == "edit" {
|
||||||
var oldTag string
|
var oldTag string
|
||||||
@@ -133,7 +143,11 @@ func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, hos
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
inboundConfig, err = s.addUsers(tx, inboundConfig, inbound.Id, inbound.Type)
|
if act == "edit" {
|
||||||
|
inboundConfig, err = s.addUsers(tx, inboundConfig, inbound.Id, inbound.Type)
|
||||||
|
} else {
|
||||||
|
inboundConfig, err = s.initUsers(tx, inboundConfig, initUsers, inbound.Id, inbound.Type)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -143,16 +157,6 @@ func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, hos
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = util.FillOutJson(&inbound, hostname)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tx.Save(&inbound).Error
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
case "del":
|
case "del":
|
||||||
var tag string
|
var tag string
|
||||||
err = json.Unmarshal(data, &tag)
|
err = json.Unmarshal(data, &tag)
|
||||||
@@ -263,7 +267,56 @@ func (s *InboundService) addUsers(db *gorm.DB, inboundJson []byte, inboundId uin
|
|||||||
inbound["users"] = usersJson
|
inbound["users"] = usersJson
|
||||||
}
|
}
|
||||||
|
|
||||||
inbound["users"] = usersJson
|
return json.Marshal(inbound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *InboundService) initUsers(db *gorm.DB, inboundJson []byte, clientIds string, inboundId uint, inboundType string) ([]byte, error) {
|
||||||
|
ClientIds := strings.Split(clientIds, ",")
|
||||||
|
if len(ClientIds) == 0 {
|
||||||
|
return inboundJson, nil
|
||||||
|
}
|
||||||
|
switch inboundType {
|
||||||
|
case "mixed", "socks", "http", "shadowsocks", "vmess", "trojan", "naive", "hysteria", "shadowtls", "tuic", "hysteria2", "vless":
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return inboundJson, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var inbound map[string]interface{}
|
||||||
|
err := json.Unmarshal(inboundJson, &inbound)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if inboundType == "shadowtls" {
|
||||||
|
version, _ := inbound["version"].(float64)
|
||||||
|
if int(version) < 3 {
|
||||||
|
return inboundJson, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if inboundType == "shadowsocks" {
|
||||||
|
method, _ := inbound["method"].(string)
|
||||||
|
if method == "2022-blake3-aes-128-gcm" {
|
||||||
|
inboundType = "shadowsocks16"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var users []string
|
||||||
|
err = db.Raw(`SELECT json_extract(clients.config, ?)
|
||||||
|
FROM clients
|
||||||
|
WHERE enable = true AND id in ?`,
|
||||||
|
"$."+inboundType, ClientIds).Scan(&users).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var usersJson []json.RawMessage
|
||||||
|
for _, user := range users {
|
||||||
|
usersJson = append(usersJson, json.RawMessage(user))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(usersJson) > 0 || inboundType != "shadowsocks" {
|
||||||
|
inbound["users"] = usersJson
|
||||||
|
}
|
||||||
|
|
||||||
return json.Marshal(inbound)
|
return json.Marshal(inbound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,34 +2,41 @@
|
|||||||
<v-card :subtitle="$t('pages.clients')">
|
<v-card :subtitle="$t('pages.clients')">
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" sm="6" md="4">
|
<v-col cols="12" sm="6" md="4">
|
||||||
<v-switch
|
<v-select v-model="data.model" :items="initUsersModels" @update:model-value="data.values = []" hide-details></v-select>
|
||||||
v-model="hasUser"
|
</v-col>
|
||||||
@change="() => {inbound.users = hasUser? [] : undefined}"
|
<v-col cols="12" sm="6" md="4" v-if="data.model == 'group'">
|
||||||
color="primary"
|
<v-select v-model="data.values" multiple chips :items="groupNames" :label="$t('client.group')" hide-details></v-select>
|
||||||
:label="$t('in.clients')"
|
</v-col>
|
||||||
hide-details></v-switch>
|
<v-col cols="12" sm="8" v-if="data.model == 'client'">
|
||||||
|
<v-select v-model="data.values" multiple chips :items="clientNames" :label="$t('pages.clients')" hide-details></v-select>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { i18n } from '@/locales';
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['inbound'],
|
props: ['data', 'clients'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hasUser: false,
|
initUsersModels: [
|
||||||
|
{ title: i18n.global.t('none'), value: 'none' },
|
||||||
|
{ title: i18n.global.t('all'), value: 'all' },
|
||||||
|
{ title: i18n.global.t('client.group'), value: 'group' },
|
||||||
|
{ title: i18n.global.t('pages.clients'), value: 'client' },
|
||||||
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
cardTitle() {
|
clientNames() {
|
||||||
this.hasUser = Object.hasOwn(this.$props.inbound,'users')
|
return this.$props.clients.map((c:any) => { return { title: c.name, value: c.id } } )
|
||||||
return this.$props.inbound?.type.toUpperCase()
|
},
|
||||||
|
groupNames() {
|
||||||
|
return Array.from(new Set(this.$props.clients.map((c:any) => c.group)))
|
||||||
},
|
},
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.hasUser = Object.hasOwn(this.$props.inbound,'users')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
<Tun v-if="inbound.type == inTypes.Tun" :data="inbound" />
|
<Tun v-if="inbound.type == inTypes.Tun" :data="inbound" />
|
||||||
<TProxy v-if="inbound.type == inTypes.TProxy" :inbound="inbound" />
|
<TProxy v-if="inbound.type == inTypes.TProxy" :inbound="inbound" />
|
||||||
<Transport v-if="Object.hasOwn(inbound,'transport')" :data="inbound" />
|
<Transport v-if="Object.hasOwn(inbound,'transport')" :data="inbound" />
|
||||||
<Users v-if="HasOptionalUser.includes(inbound.type)" :inbound="inbound" />
|
<Users v-if="hasUser" :clients="clients" :data="initUsers" />
|
||||||
<InTls v-if="HasTls.includes(inbound.type)" :inbound="inbound" :tlsConfigs="tlsConfigs" :tls_id="inbound.tls_id" />
|
<InTls v-if="HasTls.includes(inbound.type)" :inbound="inbound" :tlsConfigs="tlsConfigs" :tls_id="inbound.tls_id" />
|
||||||
<Multiplex v-if="Object.hasOwn(inbound,'multiplex')" direction="in" :data="inbound" />
|
<Multiplex v-if="Object.hasOwn(inbound,'multiplex')" direction="in" :data="inbound" />
|
||||||
</v-window-item>
|
</v-window-item>
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { InTypes, createInbound, Addr } from '@/types/inbounds'
|
import { InTypes, createInbound, Addr, inboundWithUsers, ShadowTLS } from '@/types/inbounds'
|
||||||
import RandomUtil from '@/plugins/randomUtil'
|
import RandomUtil from '@/plugins/randomUtil'
|
||||||
|
|
||||||
import Listen from '@/components/Listen.vue'
|
import Listen from '@/components/Listen.vue'
|
||||||
@@ -125,7 +125,11 @@ export default {
|
|||||||
loading: false,
|
loading: false,
|
||||||
side: "s",
|
side: "s",
|
||||||
inTypes: InTypes,
|
inTypes: InTypes,
|
||||||
HasOptionalUser: [InTypes.Mixed,InTypes.SOCKS,InTypes.HTTP,InTypes.Shadowsocks],
|
inboundWithUsers: inboundWithUsers,
|
||||||
|
initUsers: {
|
||||||
|
model: 'none',
|
||||||
|
values: <any>[],
|
||||||
|
},
|
||||||
HasInData: [
|
HasInData: [
|
||||||
InTypes.SOCKS,
|
InTypes.SOCKS,
|
||||||
InTypes.HTTP,
|
InTypes.HTTP,
|
||||||
@@ -179,6 +183,10 @@ export default {
|
|||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
this.side = "s"
|
this.side = "s"
|
||||||
|
this.initUsers = {
|
||||||
|
model: 'none',
|
||||||
|
values: [],
|
||||||
|
}
|
||||||
},
|
},
|
||||||
changeType() {
|
changeType() {
|
||||||
if (!this.inbound.listen_port) this.inbound.listen_port = RandomUtil.randomIntRange(10000, 60000)
|
if (!this.inbound.listen_port) this.inbound.listen_port = RandomUtil.randomIntRange(10000, 60000)
|
||||||
@@ -205,7 +213,22 @@ export default {
|
|||||||
},
|
},
|
||||||
saveChanges() {
|
saveChanges() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.$emit('save', this.inbound)
|
if (this.hasUser) {
|
||||||
|
let clientIds = []
|
||||||
|
switch (this.initUsers.model) {
|
||||||
|
case 'all':
|
||||||
|
clientIds = this.clients.map((c:any) => c.id)
|
||||||
|
break
|
||||||
|
case 'group':
|
||||||
|
clientIds = this.clients.filter((c:any) => this.initUsers.values.includes(c.group)).map((c:any) => c.id)
|
||||||
|
break
|
||||||
|
case 'user':
|
||||||
|
clientIds = this.initUsers.values
|
||||||
|
}
|
||||||
|
this.$emit('save', this.inbound, clientIds.length > 0 ? clientIds : undefined)
|
||||||
|
} else {
|
||||||
|
this.$emit('save', this.inbound)
|
||||||
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -217,6 +240,15 @@ export default {
|
|||||||
if (this.OnlyTLS.includes(this.inbound.type) && this.inbound.tls_id == 0) return false
|
if (this.OnlyTLS.includes(this.inbound.type) && this.inbound.tls_id == 0) return false
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
clients() {
|
||||||
|
return Data().clients?? []
|
||||||
|
},
|
||||||
|
hasUser() {
|
||||||
|
if (this.$props.id > 0) return false
|
||||||
|
if (!inboundWithUsers.includes(this.inbound.type)) return false
|
||||||
|
if (this.inbound.type == InTypes.ShadowTLS && (<ShadowTLS>this.inbound).version < 3 ) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
visible(newValue) {
|
visible(newValue) {
|
||||||
|
|||||||
@@ -64,10 +64,12 @@ const Data = defineStore('Data', {
|
|||||||
}
|
}
|
||||||
return <Client>{}
|
return <Client>{}
|
||||||
},
|
},
|
||||||
|
async save (object: string, action: string, data: any, initUsers?: number[]): 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),
|
||||||
|
initUsers: initUsers?.join(',') ?? undefined
|
||||||
}
|
}
|
||||||
const msg = await HttpUtils.post('api/save', postData)
|
const msg = await HttpUtils.post('api/save', postData)
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
|
|||||||
Reference in New Issue
Block a user