diff options
| author | Ali Rahimi <alirahimi818@gmail.com> | 2024-01-22 14:36:01 +0300 |
|---|---|---|
| committer | MHSanaei <ho3ein.sanaei@gmail.com> | 2024-01-22 14:38:36 +0300 |
| commit | b172d450e3a9dba8a56b2f6cd9e059559d232033 (patch) | |
| tree | f4a84c9a37b771eb16799d294ffafd41ef13b8b0 /web | |
| parent | 5c695ca6520c9cd9c44b18119a862f8f480969af (diff) | |
Group editing feature of users with the same subscription (#1661)
Diffstat (limited to 'web')
| -rw-r--r-- | web/controller/inbound.go | 81 | ||||
| -rw-r--r-- | web/html/xui/client_modal.html | 146 | ||||
| -rw-r--r-- | web/html/xui/form/client.html | 12 | ||||
| -rw-r--r-- | web/html/xui/inbounds.html | 33 | ||||
| -rw-r--r-- | web/translation/translate.en_US.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.es_ES.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.fa_IR.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.ru_RU.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.vi_VN.toml | 2 | ||||
| -rw-r--r-- | web/translation/translate.zh_Hans.toml | 2 |
10 files changed, 237 insertions, 47 deletions
diff --git a/web/controller/inbound.go b/web/controller/inbound.go index b274be64..4d6e0af0 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -1,6 +1,7 @@ package controller import ( + "errors" "encoding/json" "fmt" "strconv" @@ -32,7 +33,9 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) { g.POST("/clientIps/:email", a.getClientIps) g.POST("/clearClientIps/:email", a.clearClientIps) g.POST("/addClient", a.addInboundClient) + g.POST("/addGroupClient", a.addGroupInboundClient) g.POST("/:id/delClient/:clientId", a.delInboundClient) + g.POST("/updateClients", a.updateGroupInboundClient) g.POST("/updateClient/:clientId", a.updateInboundClient) g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) g.POST("/resetAllTraffics", a.resetAllTraffics) @@ -186,6 +189,34 @@ func (a *InboundController) addInboundClient(c *gin.Context) { } +func (a *InboundController) addGroupInboundClient(c *gin.Context) { + var requestData []model.Inbound + + err := c.ShouldBindJSON(&requestData) + + if err != nil { + jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) + return + } + + needRestart := true + + for _, data := range requestData { + + needRestart, err = a.inboundService.AddInboundClient(&data) + if err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + } + + jsonMsg(c, "Client(s) added", nil) + if err == nil && needRestart { + a.xrayService.SetToNeedRestart() + } + +} + func (a *InboundController) delInboundClient(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { @@ -230,6 +261,56 @@ func (a *InboundController) updateInboundClient(c *gin.Context) { } } +func (a *InboundController) updateGroupInboundClient(c *gin.Context) { + var requestData []map[string]interface{} + + if err := c.ShouldBindJSON(&requestData); err != nil { + jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) + return + } + + needRestart := false + + for _, item := range requestData { + + inboundMap, ok := item["inbound"].(map[string]interface{}) + if !ok { + jsonMsg(c, "Something went wrong!", errors.New("Failed to convert 'inbound' to map")) + return + } + + clientId, ok := item["clientId"].(string) + if !ok { + jsonMsg(c, "Something went wrong!", errors.New("Failed to convert 'clientId' to string")) + return + } + + inboundJSON, err := json.Marshal(inboundMap) + if err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + + var inboundModel model.Inbound + if err := json.Unmarshal(inboundJSON, &inboundModel); err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + + if restart, err := a.inboundService.UpdateInboundClient(&inboundModel, clientId); err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } else { + needRestart = needRestart || restart + } + } + + jsonMsg(c, "Client updated", nil) + if needRestart { + a.xrayService.SetToNeedRestart() + } +} + func (a *InboundController) resetClientTraffic(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html index 02c548e3..cb15e1e7 100644 --- a/web/html/xui/client_modal.html +++ b/web/html/xui/client_modal.html @@ -16,12 +16,15 @@ title: '', okText: '', group: { + canGroup: true, isGroup: false, currentClient: null, inbounds: [], clients: [], + editIds: [] }, dbInbound: new DBInbound(), + dbInbounds: null, inbound: new Inbound(), clients: [], clientStats: [], @@ -30,64 +33,95 @@ clientIps: null, delayedStart: false, ok() { - if (clientModal.isEdit) { - ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id, clientModal.oldClientId); - } else { - if (clientModal.group.isGroup) { - const currentClient = clientModal.group.currentClient; + if (clientModal.group.isGroup && clientModal.group.canGroup) { + const currentClient = clientModal.group.currentClient; - clientModal.group.clients.forEach((client, index) => { - const { email, limitIp, totalGB, expiryTime, reset, enable, subId, tgId, flow } = currentClient; + clientModal.group.clients.forEach((client, index) => { + const { email, limitIp, totalGB, expiryTime, reset, enable, subId, tgId, flow } = currentClient; - client.email = `${email}-${index + 1}`; - client.limitIp = limitIp; - client.totalGB = totalGB; - client.expiryTime = expiryTime; - client.reset = reset; - client.enable = enable; + const match = email.match(/^(.*?)__/); + const new_email = match ? match[1] : email; - if (subId) { - client.subId = subId; - } - if (tgId) { - client.tgId = tgId; - } - if (flow) { - client.flow = flow; - } - }); + client.email = `${new_email}__${index + 1}`; + client.limitIp = limitIp; + client.totalGB = totalGB; + client.expiryTime = expiryTime; + client.reset = reset; + client.enable = enable; + + if (subId) { + client.subId = subId; + } + if (tgId) { + client.tgId = tgId; + } + if (flow) { + client.flow = flow; + } + }); + + if (clientModal.isEdit) { + ObjectUtil.execute(clientModal.confirm, clientModal.group.clients, clientModal.group.inbounds, clientModal.group.editIds); + }else{ ObjectUtil.execute(clientModal.confirm, clientModal.group.clients, clientModal.group.inbounds); - } else { + } + } else { + if (clientModal.isEdit){ + ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id, clientModal.oldClientId); + }else{ ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id); } } }, - show({ title = '', okText = '{{ i18n "sure" }}', index = null, dbInbound = null, confirm = () => { }, isEdit = false }) { + show({ title = '', okText = '{{ i18n "sure" }}', index = null, dbInbound = null, dbInbounds = null, confirm = () => { }, isEdit = false }) { this.group = { + canGroup: true, isGroup: false, currentClient: null, inbounds: [], clients: [], + editIds: [] } + this.dbInbounds = dbInbounds; this.visible = true; this.title = title; this.okText = okText; this.isEdit = isEdit; - if (Array.isArray(dbInbound)) { - this.group.isGroup = true; - dbInbound.forEach((dbInboundItem) => { - this.showProcess(dbInboundItem); - this.group.inbounds.push(dbInboundItem.id) - this.group.clients.push(this.clients[this.index]) - }) - this.group.currentClient = this.clients[this.index] + if (dbInbounds !== null && Array.isArray(dbInbounds)) { + if (isEdit) { + this.showProcess(dbInbound, index); + let processSingleEdit = true + if (this.group.canGroup){ + this.group.currentClient = this.clients[this.index] + const response = this.getGroupInboundsClients(dbInbounds,this.group.currentClient) + if (response.clients.length > 1){ + this.group.isGroup = true; + this.group.inbounds = response.inbounds + this.group.clients = response.clients + this.group.editIds = response.editIds + if (this.clients[index].expiryTime < 0) { + this.delayedStart = true; + } + processSingleEdit = false + } + } + if(processSingleEdit){ + this.singleEditClientProcess(index) + } + } else { + this.group.isGroup = true; + dbInbounds.forEach((dbInboundItem) => { + this.showProcess(dbInboundItem); + this.addClient(this.inbound.protocol, this.clients); + this.group.inbounds.push(dbInboundItem.id) + this.group.clients.push(this.clients[this.index]) + }) + this.group.currentClient = this.clients[this.index] + } } else { this.showProcess(dbInbound, index); if (isEdit) { - if (this.clients[index].expiryTime < 0) { - this.delayedStart = true; - } - this.oldClientId = this.getClientId(dbInbound.protocol, clients[index]); + this.singleEditClientProcess(index) } else { this.addClient(this.inbound.protocol, this.clients); } @@ -101,7 +135,34 @@ this.clients = this.inbound.clients; this.index = index === null ? this.clients.length : index; this.delayedStart = false; - this.addClient(this.inbound.protocol, this.clients); + }, + singleEditClientProcess(index) { + if (this.clients[index].expiryTime < 0) { + this.delayedStart = true; + } + this.oldClientId = this.getClientId(this.dbInbound.protocol, this.clients[index]); + }, + getGroupInboundsClients(dbInbounds, currentClient) { + const response = { + inbounds: [], + clients: [], + editIds: [] + } + dbInbounds.forEach((dbInboundItem) => { + const dbInbound = new DBInbound(dbInboundItem); + const inbound = dbInbound.toInbound(); + const clients = inbound.clients; + if (clients.length > 0){ + clients.forEach((client) => { + if (client['subId'] === currentClient['subId']){ + response.inbounds.push(dbInboundItem.id) + response.clients.push(client) + response.editIds.push(this.getClientId(dbInbound.protocol, client)) + } + }) + } + }) + return response; }, getClientId(protocol, client) { switch (protocol) { @@ -148,6 +209,15 @@ get isGroup() { return this.clientModal.group.isGroup; }, + get isGroupEdit() { + return this.clientModal.group.canGroup; + }, + set isGroupEdit(value) { + this.clientModal.group.canGroup = value; + if (!value){ + this.clientModal.singleEditClientProcess(this.clientModal.index) + } + }, get datepicker() { return app.datepicker; }, diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html index f4ac25f3..434a806e 100644 --- a/web/html/xui/form/client.html +++ b/web/html/xui/form/client.html @@ -3,6 +3,18 @@ <a-form-item label='{{ i18n "pages.inbounds.enable" }}'> <a-switch v-model="client.enable"></a-switch> </a-form-item> + <a-form-item v-if="isEdit && app.subSettings.enable && isGroup"> + <template slot="label"> + <a-tooltip> + <template slot="title"> + <span>{{ i18n "pages.inbounds.isGroupEditDesc" }}</span> + </template> + {{ i18n "pages.inbounds.isGroupEdit" }} + <a-icon type="question-circle"></a-icon> + </a-tooltip> + </template> + <a-switch v-model="isGroupEdit"></a-switch> + </a-form-item> <a-form-item> <template slot="label"> <a-tooltip> diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index 53693ab3..e5d4b821 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -894,7 +894,7 @@ clientModal.show({ title: '{{ i18n "pages.client.groupAdd"}}', okText: '{{ i18n "pages.client.submitAdd"}}', - dbInbound: this.dbInbounds, + dbInbounds: this.dbInbounds, confirm: async (clients, dbInboundIds) => { clientModal.loading(); await this.addGroupClient(clients, dbInboundIds); @@ -939,6 +939,7 @@ clientModal.show({ title: '{{ i18n "pages.client.edit"}}', okText: '{{ i18n "pages.client.submitEdit"}}', + dbInbounds: this.dbInbounds, dbInbound: dbInbound, index: index, confirm: async (client, dbInboundId, clientId) => { @@ -958,10 +959,10 @@ } }, async addClient(clients, dbInboundId) { - const data = [{ + const data = { id: dbInboundId, settings: '{"clients": [' + clients.toString() + ']}', - }]; + }; await this.submit(`/panel/inbound/addClient`, data, true) }, @@ -975,14 +976,28 @@ }) }) - await this.submit(`/panel/inbound/addClient`, data, true) + await this.submit(`/panel/inbound/addGroupClient`, data, true) }, async updateClient(client, dbInboundId, clientId) { - const data = { - id: dbInboundId, - settings: '{"clients": [' + client.toString() + ']}', - }; - await this.submit(`/panel/inbound/updateClient/${clientId}`, data); + if (Array.isArray(client) && Array.isArray(dbInboundId) && Array.isArray(clientId)){ + const data = [] + client.forEach((client, index) => { + data.push({ + clientId: clientId[index], + inbound: { + id: dbInboundId[index], + settings: '{"clients": [' + client.toString() + ']}', + } + }) + }) + await this.submit(`/panel/inbound/updateClients`, data, true); + }else{ + const data = { + id: dbInboundId, + settings: '{"clients": [' + client.toString() + ']}', + }; + await this.submit(`/panel/inbound/updateClient/${clientId}`, data); + } }, resetTraffic(dbInboundId) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index b2d74c3b..4fcb50c6 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -181,6 +181,8 @@ "exportInbound" = "Export Inbound" "import" = "Import" "importInbound" = "Import an Inbound" +"isGroupEdit" = "Group editing" +"isGroupEditDesc" = "All clients with the same subscription are edited" [pages.client] "add" = "Add Client" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 83c9460b..a61689f9 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -181,6 +181,8 @@ "exportInbound" = "Exportación entrante" "import" = "Importar" "importInbound" = "Importar un entrante" +"isGroupEdit" = "Edición de grupo" +"isGroupEditDesc" = "Se editan todos los usuarios con la misma suscripción" [pages.client] "add" = "Agregar Cliente" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 9613c12e..38c28579 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -181,6 +181,8 @@ "exportInbound" = "استخراج ورودی" "import" = "افزودن" "importInbound" = "افزودن یک ورودی" +"isGroupEdit" = "ویرایش گروهی" +"isGroupEditDesc" = "تمامی کاربران با سابسکریپشن یکسان ویرایش میشوند" [pages.client] "add" = "کاربر جدید" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index 7cf2be0a..4bfda2b9 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -181,6 +181,8 @@ "exportInbound" = "Экспорт входящих" "import" = "Импортировать" "importInbound" = "Импортировать входящее сообщение" +"isGroupEdit" = "Редактирование группы" +"isGroupEditDesc" = "Редактируются все пользователи с одной подпиской" [pages.client] "add" = "Добавить пользователя" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 9cd7bc46..cd19328d 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -181,6 +181,8 @@ "exportInbound" = "Xuất nhập khẩu"
"import" = "Nhập"
"importInbound" = "Nhập inbound"
+"isGroupEdit" = "Chỉnh sửa nhóm"
+"isGroupEditDesc" = "Tất cả người dùng có cùng đăng ký đều được chỉnh sửa"
[pages.client]
"add" = "Thêm người dùng"
diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index c229dc29..a7399642 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -181,6 +181,8 @@ "exportInbound" = "出口 入境" "import"="导入" "importInbound" = "导入入站" +"isGroupEdit" = "分组编辑" +"isGroupEditDesc" = "编辑具有相同订阅的所有用户" [pages.client] "add" = "添加客户端" |
