mirror of
https://github.com/alireza0/x-ui.git
synced 2026-03-19 15:25:49 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba083ecc7e | ||
|
|
365ec1a704 | ||
|
|
63969d5fd6 | ||
|
|
0449a35409 | ||
|
|
453594ee9e | ||
|
|
a2d8bec80a | ||
|
|
b0ca8a8e6c | ||
|
|
99c9d777c0 | ||
|
|
97d109c900 | ||
|
|
35ad91a9e0 | ||
|
|
8bc16b020b | ||
|
|
6db9bd0ad9 | ||
|
|
5baa397d1c | ||
|
|
76e1243da3 | ||
|
|
7b7a0f9aa7 | ||
|
|
134e2236a6 | ||
|
|
aab672976e |
@@ -55,10 +55,11 @@ xray panel supporting multi-protocol, **Multi-lang (English,Farsi,Chinese)**
|
|||||||
| `POST` | `"/update/:id"` | Update Inbound |
|
| `POST` | `"/update/:id"` | Update Inbound |
|
||||||
| `POST` | `"/addClient/"` | Add Client to inbound |
|
| `POST` | `"/addClient/"` | Add Client to inbound |
|
||||||
| `POST` | `"/:id/delClient/:clientId"` | Delete Client by UID/Password as clientId |
|
| `POST` | `"/:id/delClient/:clientId"` | Delete Client by UID/Password as clientId |
|
||||||
| `POST` | `"/updateClient/:index"` | Update Client |
|
| `POST` | `"/updateClient/:clientId"` | Update Client by UID/Password as clientId |
|
||||||
| `POST` | `"/:id/resetClientTraffic/:email"` | Reset Client's Traffic |
|
| `POST` | `"/getClientTraffics/:email"` | Get Client's Traffic |
|
||||||
| `POST` | `"/resetAllTraffics"` | Reset traffics of all inbounds |
|
| `POST` | `"/resetAllTraffics"` | Reset traffics of all inbounds |
|
||||||
| `POST` | `"/resetAllClientTraffics/:id"` | Reset traffics of all clients in an inbound |
|
| `POST` | `"/resetAllClientTraffics/:id"` | Reset inbound clients traffics (-1: all) |
|
||||||
|
| `POST` | `"/delDepletedClients/:id"` | Delete inbound depleted clients (-1: all) |
|
||||||
|
|
||||||
# Environment Variables
|
# Environment Variables
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1.0.2
|
1.1.1
|
||||||
@@ -170,6 +170,7 @@ class AllSetting {
|
|||||||
this.webCertFile = "";
|
this.webCertFile = "";
|
||||||
this.webKeyFile = "";
|
this.webKeyFile = "";
|
||||||
this.webBasePath = "/";
|
this.webBasePath = "/";
|
||||||
|
this.sessionMaxAge = "";
|
||||||
this.expireDiff = "";
|
this.expireDiff = "";
|
||||||
this.trafficDiff = "";
|
this.trafficDiff = "";
|
||||||
this.tgBotEnable = false;
|
this.tgBotEnable = false;
|
||||||
|
|||||||
@@ -23,12 +23,13 @@ func (a *APIController) initRouter(g *gin.RouterGroup) {
|
|||||||
g.POST("/add", a.addInbound)
|
g.POST("/add", a.addInbound)
|
||||||
g.POST("/del/:id", a.delInbound)
|
g.POST("/del/:id", a.delInbound)
|
||||||
g.POST("/update/:id", a.updateInbound)
|
g.POST("/update/:id", a.updateInbound)
|
||||||
g.POST("/addClient/", a.addInboundClient)
|
g.POST("/addClient", a.addInboundClient)
|
||||||
g.POST("/:id/delClient/:clientId", a.delInboundClient)
|
g.POST("/:id/delClient/:clientId", a.delInboundClient)
|
||||||
g.POST("/updateClient/:index", a.updateInboundClient)
|
g.POST("/updateClient/:clientId", a.updateInboundClient)
|
||||||
g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
|
g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
|
||||||
g.POST("/resetAllTraffics", a.resetAllTraffics)
|
g.POST("/resetAllTraffics", a.resetAllTraffics)
|
||||||
g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics)
|
g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics)
|
||||||
|
g.POST("/delDepletedClients/:id", a.delDepletedClients)
|
||||||
|
|
||||||
a.inboundController = NewInboundController(g)
|
a.inboundController = NewInboundController(g)
|
||||||
}
|
}
|
||||||
@@ -69,3 +70,6 @@ func (a *APIController) resetAllTraffics(c *gin.Context) {
|
|||||||
func (a *APIController) resetAllClientTraffics(c *gin.Context) {
|
func (a *APIController) resetAllClientTraffics(c *gin.Context) {
|
||||||
a.inboundController.resetAllClientTraffics(c)
|
a.inboundController.resetAllClientTraffics(c)
|
||||||
}
|
}
|
||||||
|
func (a *APIController) delDepletedClients(c *gin.Context) {
|
||||||
|
a.inboundController.delDepletedClients(c)
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,10 +33,11 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
|
|||||||
g.POST("/update/:id", a.updateInbound)
|
g.POST("/update/:id", a.updateInbound)
|
||||||
g.POST("/addClient", a.addInboundClient)
|
g.POST("/addClient", a.addInboundClient)
|
||||||
g.POST("/:id/delClient/:clientId", a.delInboundClient)
|
g.POST("/:id/delClient/:clientId", a.delInboundClient)
|
||||||
g.POST("/updateClient/:index", a.updateInboundClient)
|
g.POST("/updateClient/:clientId", a.updateInboundClient)
|
||||||
g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
|
g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
|
||||||
g.POST("/resetAllTraffics", a.resetAllTraffics)
|
g.POST("/resetAllTraffics", a.resetAllTraffics)
|
||||||
g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics)
|
g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics)
|
||||||
|
g.POST("/delDepletedClients/:id", a.delDepletedClients)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ func (a *InboundController) addInboundClient(c *gin.Context) {
|
|||||||
|
|
||||||
err = a.inboundService.AddInboundClient(data)
|
err = a.inboundService.AddInboundClient(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "Client(s) added", nil)
|
jsonMsg(c, "Client(s) added", nil)
|
||||||
@@ -166,7 +167,7 @@ func (a *InboundController) delInboundClient(c *gin.Context) {
|
|||||||
|
|
||||||
err = a.inboundService.DelInboundClient(id, clientId)
|
err = a.inboundService.DelInboundClient(id, clientId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "Client deleted", nil)
|
jsonMsg(c, "Client deleted", nil)
|
||||||
@@ -176,22 +177,18 @@ func (a *InboundController) delInboundClient(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *InboundController) updateInboundClient(c *gin.Context) {
|
func (a *InboundController) updateInboundClient(c *gin.Context) {
|
||||||
index, err := strconv.Atoi(c.Param("index"))
|
clientId := c.Param("clientId")
|
||||||
if err != nil {
|
|
||||||
jsonMsg(c, I18n(c, "pages.inbounds.revise"), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
inbound := &model.Inbound{}
|
inbound := &model.Inbound{}
|
||||||
err = c.ShouldBind(inbound)
|
err := c.ShouldBind(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c, "pages.inbounds.revise"), err)
|
jsonMsg(c, I18n(c, "pages.inbounds.revise"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.inboundService.UpdateInboundClient(inbound, index)
|
err = a.inboundService.UpdateInboundClient(inbound, clientId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "Client updated", nil)
|
jsonMsg(c, "Client updated", nil)
|
||||||
@@ -210,7 +207,7 @@ func (a *InboundController) resetClientTraffic(c *gin.Context) {
|
|||||||
|
|
||||||
err = a.inboundService.ResetClientTraffic(id, email)
|
err = a.inboundService.ResetClientTraffic(id, email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "traffic reseted", nil)
|
jsonMsg(c, "traffic reseted", nil)
|
||||||
@@ -222,7 +219,7 @@ func (a *InboundController) resetClientTraffic(c *gin.Context) {
|
|||||||
func (a *InboundController) resetAllTraffics(c *gin.Context) {
|
func (a *InboundController) resetAllTraffics(c *gin.Context) {
|
||||||
err := a.inboundService.ResetAllTraffics()
|
err := a.inboundService.ResetAllTraffics()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "All traffics reseted", nil)
|
jsonMsg(c, "All traffics reseted", nil)
|
||||||
@@ -237,8 +234,22 @@ func (a *InboundController) resetAllClientTraffics(c *gin.Context) {
|
|||||||
|
|
||||||
err = a.inboundService.ResetAllClientTraffics(id)
|
err = a.inboundService.ResetAllClientTraffics(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "All traffics of client reseted", nil)
|
jsonMsg(c, "All traffics of client reseted", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *InboundController) delDepletedClients(c *gin.Context) {
|
||||||
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
|
if err != nil {
|
||||||
|
jsonMsg(c, I18n(c, "pages.inbounds.revise"), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = a.inboundService.DelDepletedClients(id)
|
||||||
|
if err != nil {
|
||||||
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
jsonMsg(c, "All delpeted clients are deleted", nil)
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ type LoginForm struct {
|
|||||||
type IndexController struct {
|
type IndexController struct {
|
||||||
BaseController
|
BaseController
|
||||||
|
|
||||||
userService service.UserService
|
settingService service.SettingService
|
||||||
tgbot service.Tgbot
|
userService service.UserService
|
||||||
|
tgbot service.Tgbot
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIndexController(g *gin.RouterGroup) *IndexController {
|
func NewIndexController(g *gin.RouterGroup) *IndexController {
|
||||||
@@ -69,6 +70,16 @@ func (a *IndexController) login(c *gin.Context) {
|
|||||||
a.tgbot.UserLoginNotify(form.Username, getRemoteIp(c), timeStr, 1)
|
a.tgbot.UserLoginNotify(form.Username, getRemoteIp(c), timeStr, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionMaxAge, err := a.settingService.GetSessionMaxAge()
|
||||||
|
if err != nil {
|
||||||
|
logger.Infof("Unable to get session's max age from DB")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = session.SetMaxAge(c, sessionMaxAge*60)
|
||||||
|
if err != nil {
|
||||||
|
logger.Infof("Unable to set session's max age")
|
||||||
|
}
|
||||||
|
|
||||||
err = session.SetLoginUser(c, user)
|
err = session.SetLoginUser(c, user)
|
||||||
logger.Info("user", user.Id, "login success")
|
logger.Info("user", user.Id, "login success")
|
||||||
jsonMsg(c, I18n(c, "pages.login.toasts.successLogin"), err)
|
jsonMsg(c, I18n(c, "pages.login.toasts.successLogin"), err)
|
||||||
|
|||||||
@@ -1,24 +1,16 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"x-ui/config"
|
"x-ui/config"
|
||||||
"x-ui/logger"
|
"x-ui/logger"
|
||||||
"x-ui/web/entity"
|
"x-ui/web/entity"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getUriId(c *gin.Context) int64 {
|
|
||||||
s := struct {
|
|
||||||
Id int64 `uri:"id"`
|
|
||||||
}{}
|
|
||||||
|
|
||||||
_ = c.BindUri(&s)
|
|
||||||
return s.Id
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRemoteIp(c *gin.Context) string {
|
func getRemoteIp(c *gin.Context) string {
|
||||||
value := c.GetHeader("X-Forwarded-For")
|
value := c.GetHeader("X-Forwarded-For")
|
||||||
if value != "" {
|
if value != "" {
|
||||||
@@ -75,6 +67,7 @@ func html(c *gin.Context, name string, title string, data gin.H) {
|
|||||||
data = gin.H{}
|
data = gin.H{}
|
||||||
}
|
}
|
||||||
data["title"] = title
|
data["title"] = title
|
||||||
|
data["host"] = strings.Split(c.Request.Host, ":")[0]
|
||||||
data["request_uri"] = c.Request.RequestURI
|
data["request_uri"] = c.Request.RequestURI
|
||||||
data["base_path"] = c.GetString("base_path")
|
data["base_path"] = c.GetString("base_path")
|
||||||
c.HTML(http.StatusOK, name, getContext(data))
|
c.HTML(http.StatusOK, name, getContext(data))
|
||||||
@@ -84,10 +77,8 @@ func getContext(h gin.H) gin.H {
|
|||||||
a := gin.H{
|
a := gin.H{
|
||||||
"cur_ver": config.GetVersion(),
|
"cur_ver": config.GetVersion(),
|
||||||
}
|
}
|
||||||
if h != nil {
|
for key, value := range h {
|
||||||
for key, value := range h {
|
a[key] = value
|
||||||
a[key] = value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ type AllSetting struct {
|
|||||||
WebCertFile string `json:"webCertFile" form:"webCertFile"`
|
WebCertFile string `json:"webCertFile" form:"webCertFile"`
|
||||||
WebKeyFile string `json:"webKeyFile" form:"webKeyFile"`
|
WebKeyFile string `json:"webKeyFile" form:"webKeyFile"`
|
||||||
WebBasePath string `json:"webBasePath" form:"webBasePath"`
|
WebBasePath string `json:"webBasePath" form:"webBasePath"`
|
||||||
|
SessionMaxAge int `json:"sessionMaxAge" form:"sessionMaxAge"`
|
||||||
ExpireDiff int `json:"expireDiff" form:"expireDiff"`
|
ExpireDiff int `json:"expireDiff" form:"expireDiff"`
|
||||||
TrafficDiff int `json:"trafficDiff" form:"trafficDiff"`
|
TrafficDiff int `json:"trafficDiff" form:"trafficDiff"`
|
||||||
TgBotEnable bool `json:"tgBotEnable" form:"tgBotEnable"`
|
TgBotEnable bool `json:"tgBotEnable" form:"tgBotEnable"`
|
||||||
|
|||||||
@@ -13,6 +13,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<title>{{ i18n .title}}</title>
|
<title>{{ .host }}-{{ i18n .title}}</title>
|
||||||
</head>
|
</head>
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -17,12 +17,13 @@
|
|||||||
inbound: new Inbound(),
|
inbound: new Inbound(),
|
||||||
clients: [],
|
clients: [],
|
||||||
clientStats: [],
|
clientStats: [],
|
||||||
|
oldClientId: "",
|
||||||
index: null,
|
index: null,
|
||||||
isExpired: false,
|
isExpired: false,
|
||||||
delayedStart: false,
|
delayedStart: false,
|
||||||
ok() {
|
ok() {
|
||||||
if(clientModal.isEdit){
|
if(clientModal.isEdit){
|
||||||
ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id, clientModal.index);
|
ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id, clientModal.oldClientId);
|
||||||
} else {
|
} else {
|
||||||
ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id);
|
ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id);
|
||||||
}
|
}
|
||||||
@@ -38,12 +39,13 @@
|
|||||||
this.index = index === null ? this.clients.length : index;
|
this.index = index === null ? this.clients.length : index;
|
||||||
this.isExpired = isEdit ? this.inbound.isExpiry(this.index) : false;
|
this.isExpired = isEdit ? this.inbound.isExpiry(this.index) : false;
|
||||||
this.delayedStart = false;
|
this.delayedStart = false;
|
||||||
if (!isEdit){
|
if (isEdit){
|
||||||
this.addClient(this.inbound.protocol, this.clients);
|
|
||||||
} else {
|
|
||||||
if (this.clients[index].expiryTime < 0){
|
if (this.clients[index].expiryTime < 0){
|
||||||
this.delayedStart = true;
|
this.delayedStart = true;
|
||||||
}
|
}
|
||||||
|
this.oldClientId = this.dbInbound.protocol == "trojan" ? this.clients[index].password : this.clients[index].id;
|
||||||
|
} else {
|
||||||
|
this.addClient(this.inbound.protocol, this.clients);
|
||||||
}
|
}
|
||||||
this.clientStats = this.dbInbound.clientStats.find(row => row.email === this.clients[this.index].email);
|
this.clientStats = this.dbInbound.clientStats.find(row => row.email === this.clients[this.index].email);
|
||||||
this.confirm = confirm;
|
this.confirm = confirm;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<a-input :value="value" @input="$emit('input', $event.target.value)"></a-input>
|
<a-input :value="value" @input="$emit('input', $event.target.value)"></a-input>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="type === 'number'">
|
<template v-else-if="type === 'number'">
|
||||||
<a-input type="number" :value="value" @input="$emit('input', $event.target.value)"></a-input>
|
<a-input type="number" :value="value" @input="$emit('input', $event.target.value)" :min="min"></a-input>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="type === 'textarea'">
|
<template v-else-if="type === 'textarea'">
|
||||||
<a-textarea :value="value" @input="$emit('input', $event.target.value)" :auto-size="{ minRows: 10, maxRows: 10 }"></a-textarea>
|
<a-textarea :value="value" @input="$emit('input', $event.target.value)" :auto-size="{ minRows: 10, maxRows: 10 }"></a-textarea>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
{{define "component/setting"}}
|
{{define "component/setting"}}
|
||||||
<script>
|
<script>
|
||||||
Vue.component('setting-list-item', {
|
Vue.component('setting-list-item', {
|
||||||
props: ["type", "title", "desc", "value"],
|
props: ["type", "title", "desc", "value", "min"],
|
||||||
template: `{{template "component/settingListItem"}}`,
|
template: `{{template "component/settingListItem"}}`,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -67,8 +67,27 @@
|
|||||||
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
|
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
|
||||||
<div slot="title">
|
<div slot="title">
|
||||||
<a-button type="primary" icon="plus" @click="openAddInbound">{{ i18n "pages.inbounds.addInbound" }}</a-button>
|
<a-button type="primary" icon="plus" @click="openAddInbound">{{ i18n "pages.inbounds.addInbound" }}</a-button>
|
||||||
<a-button type="primary" icon="export" @click="exportAllLinks">{{ i18n "pages.inbounds.export" }}</a-button>
|
<a-dropdown :trigger="['click']">
|
||||||
<a-button type="primary" icon="reload" @click="resetAllTraffic">{{ i18n "pages.inbounds.resetAllTraffic" }}</a-button>
|
<a-button type="primary" icon="menu">{{ i18n "pages.inbounds.generalActions" }}</a-button>
|
||||||
|
<a-menu slot="overlay" @click="a => generalActions(a)" :theme="siderDrawer.theme">
|
||||||
|
<a-menu-item key="export">
|
||||||
|
<a-icon type="export"></a-icon>
|
||||||
|
{{ i18n "pages.inbounds.export" }}
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="resetInbounds">
|
||||||
|
<a-icon type="reload"></a-icon>
|
||||||
|
{{ i18n "pages.inbounds.resetAllTraffic" }}
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="resetClients">
|
||||||
|
<a-icon type="file-done"></a-icon>
|
||||||
|
{{ i18n "pages.inbounds.resetAllClientTraffics" }}
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="delDepletedClients">
|
||||||
|
<a-icon type="rest"></a-icon>
|
||||||
|
{{ i18n "pages.inbounds.delDepletedClients" }}
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
</div>
|
</div>
|
||||||
<a-input v-model.lazy="searchKey" placeholder="{{ i18n "search" }}" autofocus style="max-width: 300px"></a-input>
|
<a-input v-model.lazy="searchKey" placeholder="{{ i18n "search" }}" autofocus style="max-width: 300px"></a-input>
|
||||||
<a-table :columns="columns" :row-key="dbInbound => dbInbound.id"
|
<a-table :columns="columns" :row-key="dbInbound => dbInbound.id"
|
||||||
@@ -100,12 +119,16 @@
|
|||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="resetClients">
|
<a-menu-item key="resetClients">
|
||||||
<a-icon type="file-done"></a-icon>
|
<a-icon type="file-done"></a-icon>
|
||||||
{{ i18n "pages.inbounds.resetAllClientTraffics"}}
|
{{ i18n "pages.inbounds.resetInboundClientTraffics"}}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="export">
|
<a-menu-item key="export">
|
||||||
<a-icon type="export"></a-icon>
|
<a-icon type="export"></a-icon>
|
||||||
{{ i18n "pages.inbounds.export"}}
|
{{ i18n "pages.inbounds.export"}}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
|
<a-menu-item key="delDepletedClients">
|
||||||
|
<a-icon type="rest"></a-icon>
|
||||||
|
{{ i18n "pages.inbounds.delDepletedClients" }}
|
||||||
|
</a-menu-item>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-menu-item key="showInfo">
|
<a-menu-item key="showInfo">
|
||||||
@@ -387,6 +410,22 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
generalActions(action){
|
||||||
|
switch (action.key) {
|
||||||
|
case "export":
|
||||||
|
this.exportAllLinks();
|
||||||
|
break;
|
||||||
|
case "resetInbounds":
|
||||||
|
this.resetAllTraffic();
|
||||||
|
break;
|
||||||
|
case "resetClients":
|
||||||
|
this.resetAllClientTraffics(-1);
|
||||||
|
break;
|
||||||
|
case "delDepletedClients":
|
||||||
|
this.delDepletedClients(-1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
clickAction(action, dbInbound) {
|
clickAction(action, dbInbound) {
|
||||||
switch (action.key) {
|
switch (action.key) {
|
||||||
case "qrcode":
|
case "qrcode":
|
||||||
@@ -419,6 +458,9 @@
|
|||||||
case "delete":
|
case "delete":
|
||||||
this.delInbound(dbInbound.id);
|
this.delInbound(dbInbound.id);
|
||||||
break;
|
break;
|
||||||
|
case "delDepletedClients":
|
||||||
|
this.delDepletedClients(dbInbound.id)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openAddInbound() {
|
openAddInbound() {
|
||||||
@@ -558,9 +600,9 @@
|
|||||||
okText: '{{ i18n "pages.client.submitEdit"}}',
|
okText: '{{ i18n "pages.client.submitEdit"}}',
|
||||||
dbInbound: dbInbound,
|
dbInbound: dbInbound,
|
||||||
index: index,
|
index: index,
|
||||||
confirm: async (client, dbInboundId, index) => {
|
confirm: async (client, dbInboundId, clientId) => {
|
||||||
clientModal.loading();
|
clientModal.loading();
|
||||||
await this.updateClient(client, dbInboundId, index);
|
await this.updateClient(client, dbInboundId, clientId);
|
||||||
clientModal.close();
|
clientModal.close();
|
||||||
},
|
},
|
||||||
isEdit: true
|
isEdit: true
|
||||||
@@ -577,12 +619,12 @@
|
|||||||
};
|
};
|
||||||
await this.submit(`/xui/inbound/addClient`, data);
|
await this.submit(`/xui/inbound/addClient`, data);
|
||||||
},
|
},
|
||||||
async updateClient(client, dbInboundId, index) {
|
async updateClient(client, dbInboundId, clientId) {
|
||||||
const data = {
|
const data = {
|
||||||
id: dbInboundId,
|
id: dbInboundId,
|
||||||
settings: '{"clients": [' + client.toString() +']}',
|
settings: '{"clients": [' + client.toString() +']}',
|
||||||
};
|
};
|
||||||
await this.submit(`/xui/inbound/updateClient/${index}`, data);
|
await this.submit(`/xui/inbound/updateClient/${clientId}`, data);
|
||||||
},
|
},
|
||||||
resetTraffic(dbInboundId) {
|
resetTraffic(dbInboundId) {
|
||||||
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
||||||
@@ -648,7 +690,8 @@
|
|||||||
clients = this.getClients(dbInbound.protocol, inbound.settings);
|
clients = this.getClients(dbInbound.protocol, inbound.settings);
|
||||||
index = this.findIndexOfClient(clients, client);
|
index = this.findIndexOfClient(clients, client);
|
||||||
clients[index].enable = !clients[index].enable;
|
clients[index].enable = !clients[index].enable;
|
||||||
await this.updateClient(clients[index],dbInboundId, index);
|
clientId = dbInbound.protocol == "trojan" ? clients[index].password : clients[index].id;
|
||||||
|
await this.updateClient(clients[index],dbInboundId, clientId);
|
||||||
this.loading(false);
|
this.loading(false);
|
||||||
},
|
},
|
||||||
async submit(url, data) {
|
async submit(url, data) {
|
||||||
@@ -688,14 +731,24 @@
|
|||||||
},
|
},
|
||||||
resetAllClientTraffics(dbInboundId) {
|
resetAllClientTraffics(dbInboundId) {
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '{{ i18n "pages.inbounds.resetAllClientTrafficTitle"}}',
|
title: dbInboundId>0 ? '{{ i18n "pages.inbounds.resetInboundClientTrafficTitle"}}' : '{{ i18n "pages.inbounds.resetAllClientTrafficTitle"}}',
|
||||||
content: '{{ i18n "pages.inbounds.resetAllClientTrafficContent"}}',
|
content: dbInboundId>0 ? '{{ i18n "pages.inbounds.resetInboundClientTrafficContent"}}' : '{{ i18n "pages.inbounds.resetAllClientTrafficContent"}}',
|
||||||
class: siderDrawer.isDarkTheme ? darkClass : '',
|
class: siderDrawer.isDarkTheme ? darkClass : '',
|
||||||
okText: '{{ i18n "reset"}}',
|
okText: '{{ i18n "reset"}}',
|
||||||
cancelText: '{{ i18n "cancel"}}',
|
cancelText: '{{ i18n "cancel"}}',
|
||||||
onOk: () => this.submit('/xui/inbound/resetAllClientTraffics/' + dbInboundId),
|
onOk: () => this.submit('/xui/inbound/resetAllClientTraffics/' + dbInboundId),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
delDepletedClients(dbInboundId) {
|
||||||
|
this.$confirm({
|
||||||
|
title: '{{ i18n "pages.inbounds.delDepletedClientsTitle"}}',
|
||||||
|
content: '{{ i18n "pages.inbounds.delDepletedClientsContent"}}',
|
||||||
|
class: siderDrawer.isDarkTheme ? darkClass : '',
|
||||||
|
okText: '{{ i18n "reset"}}',
|
||||||
|
cancelText: '{{ i18n "cancel"}}',
|
||||||
|
onOk: () => this.submit('/xui/inbound/delDepletedClients/' + dbInboundId),
|
||||||
|
})
|
||||||
|
},
|
||||||
isExpiry(dbInbound, index) {
|
isExpiry(dbInbound, index) {
|
||||||
return dbInbound.toInbound().isExpiry(index)
|
return dbInbound.toInbound().isExpiry(index)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.publicKeyPath"}}' desc='{{ i18n "pages.setting.publicKeyPathDesc"}}' v-model="allSetting.webCertFile"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.publicKeyPath"}}' desc='{{ i18n "pages.setting.publicKeyPathDesc"}}' v-model="allSetting.webCertFile"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.privateKeyPath"}}' desc='{{ i18n "pages.setting.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.privateKeyPath"}}' desc='{{ i18n "pages.setting.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.panelUrlPath"}}' desc='{{ i18n "pages.setting.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.panelUrlPath"}}' desc='{{ i18n "pages.setting.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>
|
||||||
|
<setting-list-item type="number" title='{{ i18n "pages.setting.sessionMaxAge" }}' desc='{{ i18n "pages.setting.sessionMaxAgeDesc" }}' v-model="allSetting.sessionMaxAge" :min="0"></setting-list-item>
|
||||||
<setting-list-item type="number" title='{{ i18n "pages.setting.expireTimeDiff" }}' desc='{{ i18n "pages.setting.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
|
<setting-list-item type="number" title='{{ i18n "pages.setting.expireTimeDiff" }}' desc='{{ i18n "pages.setting.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
|
||||||
<setting-list-item type="number" title='{{ i18n "pages.setting.trafficDiff" }}' desc='{{ i18n "pages.setting.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
|
<setting-list-item type="number" title='{{ i18n "pages.setting.trafficDiff" }}' desc='{{ i18n "pages.setting.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
|
||||||
<a-list-item>
|
<a-list-item>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package service
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"x-ui/database"
|
"x-ui/database"
|
||||||
"x-ui/database/model"
|
"x-ui/database/model"
|
||||||
@@ -347,7 +348,7 @@ func (s *InboundService) DelInboundClient(inboundId int, clientId string) error
|
|||||||
return db.Save(oldInbound).Error
|
return db.Save(oldInbound).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) UpdateInboundClient(data *model.Inbound, index int) error {
|
func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId string) error {
|
||||||
clients, err := s.getClients(data)
|
clients, err := s.getClients(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -371,7 +372,23 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, index int) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clients[0].Email) > 0 && clients[0].Email != oldClients[index].Email {
|
oldEmail := ""
|
||||||
|
clientIndex := 0
|
||||||
|
for index, oldClient := range oldClients {
|
||||||
|
oldClientId := ""
|
||||||
|
if oldInbound.Protocol == "trojan" {
|
||||||
|
oldClientId = oldClient.Password
|
||||||
|
} else {
|
||||||
|
oldClientId = oldClient.ID
|
||||||
|
}
|
||||||
|
if clientId == oldClientId {
|
||||||
|
oldEmail = oldClient.Email
|
||||||
|
clientIndex = index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(clients[0].Email) > 0 && clients[0].Email != oldEmail {
|
||||||
existEmail, err := s.checkEmailsExistForClients(clients)
|
existEmail, err := s.checkEmailsExistForClients(clients)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -386,10 +403,8 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, index int) err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsClients := oldSettings["clients"].([]interface{})
|
settingsClients := oldSettings["clients"].([]interface{})
|
||||||
settingsClients[index] = inerfaceClients[0]
|
settingsClients[clientIndex] = inerfaceClients[0]
|
||||||
|
|
||||||
oldSettings["clients"] = settingsClients
|
oldSettings["clients"] = settingsClients
|
||||||
|
|
||||||
newSettings, err := json.MarshalIndent(oldSettings, "", " ")
|
newSettings, err := json.MarshalIndent(oldSettings, "", " ")
|
||||||
@@ -401,8 +416,8 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, index int) err
|
|||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
if len(clients[0].Email) > 0 {
|
if len(clients[0].Email) > 0 {
|
||||||
if len(oldClients[index].Email) > 0 {
|
if len(oldEmail) > 0 {
|
||||||
err = s.UpdateClientStat(oldClients[index].Email, &clients[0])
|
err = s.UpdateClientStat(oldEmail, &clients[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -410,7 +425,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, index int) err
|
|||||||
s.AddClientStat(data.Id, &clients[0])
|
s.AddClientStat(data.Id, &clients[0])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = s.DelClientStat(db, oldClients[index].Email)
|
err = s.DelClientStat(db, oldEmail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -513,7 +528,7 @@ func (s *InboundService) adjustTraffics(tx *gorm.DB, dbClientTraffics []*xray.Cl
|
|||||||
for client_index := range clients {
|
for client_index := range clients {
|
||||||
c := clients[client_index].(map[string]interface{})
|
c := clients[client_index].(map[string]interface{})
|
||||||
for traffic_index := range dbClientTraffics {
|
for traffic_index := range dbClientTraffics {
|
||||||
if c["email"] == dbClientTraffics[traffic_index].Email {
|
if dbClientTraffics[traffic_index].ExpiryTime < 0 && c["email"] == dbClientTraffics[traffic_index].Email {
|
||||||
oldExpiryTime := c["expiryTime"].(float64)
|
oldExpiryTime := c["expiryTime"].(float64)
|
||||||
newExpiryTime := (time.Now().Unix() * 1000) - int64(oldExpiryTime)
|
newExpiryTime := (time.Now().Unix() * 1000) - int64(oldExpiryTime)
|
||||||
c["expiryTime"] = newExpiryTime
|
c["expiryTime"] = newExpiryTime
|
||||||
@@ -629,8 +644,15 @@ func (s *InboundService) ResetClientTraffic(id int, clientEmail string) error {
|
|||||||
func (s *InboundService) ResetAllClientTraffics(id int) error {
|
func (s *InboundService) ResetAllClientTraffics(id int) error {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
|
whereText := "inbound_id "
|
||||||
|
if id == -1 {
|
||||||
|
whereText += " > ?"
|
||||||
|
} else {
|
||||||
|
whereText += " = ?"
|
||||||
|
}
|
||||||
|
|
||||||
result := db.Model(xray.ClientTraffic{}).
|
result := db.Model(xray.ClientTraffic{}).
|
||||||
Where("inbound_id = ?", id).
|
Where(whereText, id).
|
||||||
Updates(map[string]interface{}{"enable": true, "up": 0, "down": 0})
|
Updates(map[string]interface{}{"enable": true, "up": 0, "down": 0})
|
||||||
|
|
||||||
err := result.Error
|
err := result.Error
|
||||||
@@ -656,6 +678,84 @@ func (s *InboundService) ResetAllTraffics() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *InboundService) DelDepletedClients(id int) (err error) {
|
||||||
|
db := database.GetDB()
|
||||||
|
tx := db.Begin()
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
tx.Commit()
|
||||||
|
} else {
|
||||||
|
tx.Rollback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
whereText := "inbound_id "
|
||||||
|
if id < 0 {
|
||||||
|
whereText += "> ?"
|
||||||
|
} else {
|
||||||
|
whereText += "= ?"
|
||||||
|
}
|
||||||
|
|
||||||
|
depletedClients := []xray.ClientTraffic{}
|
||||||
|
err = db.Model(xray.ClientTraffic{}).Where(whereText+" and enable = ?", id, false).Select("inbound_id, GROUP_CONCAT(email) as email").Group("inbound_id").Find(&depletedClients).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, depletedClient := range depletedClients {
|
||||||
|
emails := strings.Split(depletedClient.Email, ",")
|
||||||
|
oldInbound, err := s.GetInbound(depletedClient.InboundId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var oldSettings map[string]interface{}
|
||||||
|
err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
oldClients := oldSettings["clients"].([]interface{})
|
||||||
|
var newClients []interface{}
|
||||||
|
for _, client := range oldClients {
|
||||||
|
deplete := false
|
||||||
|
c := client.(map[string]interface{})
|
||||||
|
for _, email := range emails {
|
||||||
|
if email == c["email"].(string) {
|
||||||
|
deplete = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !deplete {
|
||||||
|
newClients = append(newClients, client)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(newClients) > 0 {
|
||||||
|
oldSettings["clients"] = newClients
|
||||||
|
|
||||||
|
newSettings, err := json.MarshalIndent(oldSettings, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
oldInbound.Settings = string(newSettings)
|
||||||
|
err = tx.Save(oldInbound).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Delete inbound if no client remains
|
||||||
|
s.DelInbound(depletedClient.InboundId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Where(whereText+" and enable = ?", id, false).Delete(xray.ClientTraffic{}).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *InboundService) GetClientTrafficTgBot(tguname string) ([]*xray.ClientTraffic, error) {
|
func (s *InboundService) GetClientTrafficTgBot(tguname string) ([]*xray.ClientTraffic, error) {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
var inbounds []*model.Inbound
|
var inbounds []*model.Inbound
|
||||||
@@ -786,6 +886,19 @@ func (s *InboundService) MigrationRequirements() {
|
|||||||
|
|
||||||
inbounds[inbound_index].Settings = string(modifiedSettings)
|
inbounds[inbound_index].Settings = string(modifiedSettings)
|
||||||
}
|
}
|
||||||
|
modelClients, err := s.getClients(inbounds[inbound_index])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, modelClient := range modelClients {
|
||||||
|
if len(modelClient.Email) > 0 {
|
||||||
|
var count int64
|
||||||
|
db.Model(xray.ClientTraffic{}).Where("email = ?", modelClient.Email).Count(&count)
|
||||||
|
if count == 0 {
|
||||||
|
s.AddClientStat(inbounds[inbound_index].Id, &modelClient)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
db.Save(inbounds)
|
db.Save(inbounds)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ var defaultValueMap = map[string]string{
|
|||||||
"webKeyFile": "",
|
"webKeyFile": "",
|
||||||
"secret": random.Seq(32),
|
"secret": random.Seq(32),
|
||||||
"webBasePath": "/",
|
"webBasePath": "/",
|
||||||
|
"sessionMaxAge": "0",
|
||||||
"expireDiff": "0",
|
"expireDiff": "0",
|
||||||
"trafficDiff": "0",
|
"trafficDiff": "0",
|
||||||
"timeLocation": "Asia/Tehran",
|
"timeLocation": "Asia/Tehran",
|
||||||
@@ -234,18 +235,10 @@ func (s *SettingService) GetTgBotBackup() (bool, error) {
|
|||||||
return s.getBool("tgBotBackup")
|
return s.getBool("tgBotBackup")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SettingService) SetTgBotBackup(value bool) error {
|
|
||||||
return s.setBool("tgBotBackup", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SettingService) GetTgCpu() (int, error) {
|
func (s *SettingService) GetTgCpu() (int, error) {
|
||||||
return s.getInt("tgCpu")
|
return s.getInt("tgCpu")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SettingService) SetTgCpu(value int) error {
|
|
||||||
return s.setInt("tgCpu", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SettingService) GetPort() (int, error) {
|
func (s *SettingService) GetPort() (int, error) {
|
||||||
return s.getInt("webPort")
|
return s.getInt("webPort")
|
||||||
}
|
}
|
||||||
@@ -266,16 +259,12 @@ func (s *SettingService) GetExpireDiff() (int, error) {
|
|||||||
return s.getInt("expireDiff")
|
return s.getInt("expireDiff")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SettingService) SetExpireDiff(value int) error {
|
|
||||||
return s.setInt("expireDiff", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SettingService) GetTrafficDiff() (int, error) {
|
func (s *SettingService) GetTrafficDiff() (int, error) {
|
||||||
return s.getInt("trafficDiff")
|
return s.getInt("trafficDiff")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SettingService) SetgetTrafficDiff(value int) error {
|
func (s *SettingService) GetSessionMaxAge() (int, error) {
|
||||||
return s.setInt("trafficDiff", value)
|
return s.getInt("sessionMaxAge")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SettingService) GetSecret() ([]byte, error) {
|
func (s *SettingService) GetSecret() ([]byte, error) {
|
||||||
|
|||||||
@@ -532,7 +532,11 @@ func searchHost(headers interface{}) string {
|
|||||||
switch v.(type) {
|
switch v.(type) {
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
hosts, _ := v.([]interface{})
|
hosts, _ := v.([]interface{})
|
||||||
return hosts[0].(string)
|
if len(hosts) > 0 {
|
||||||
|
return hosts[0].(string)
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
case interface{}:
|
case interface{}:
|
||||||
return v.(string)
|
return v.(string)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,9 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
|
|||||||
if key != "email" && key != "id" && key != "password" && key != "flow" && key != "alterId" {
|
if key != "email" && key != "id" && key != "password" && key != "flow" && key != "alterId" {
|
||||||
delete(c, key)
|
delete(c, key)
|
||||||
}
|
}
|
||||||
|
if c["flow"] == "xtls-rprx-vision-udp443" {
|
||||||
|
c["flow"] = "xtls-rprx-vision"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
final_clients = append(final_clients, interface{}(c))
|
final_clients = append(final_clients, interface{}(c))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package session
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
|
"x-ui/database/model"
|
||||||
|
|
||||||
"github.com/gin-contrib/sessions"
|
"github.com/gin-contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"x-ui/database/model"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,6 +22,15 @@ func SetLoginUser(c *gin.Context, user *model.User) error {
|
|||||||
return s.Save()
|
return s.Save()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetMaxAge(c *gin.Context, maxAge int) error {
|
||||||
|
s := sessions.Default(c)
|
||||||
|
s.Options(sessions.Options{
|
||||||
|
Path: "/",
|
||||||
|
MaxAge: maxAge,
|
||||||
|
})
|
||||||
|
return s.Save()
|
||||||
|
}
|
||||||
|
|
||||||
func GetLoginUser(c *gin.Context) *model.User {
|
func GetLoginUser(c *gin.Context) *model.User {
|
||||||
s := sessions.Default(c)
|
s := sessions.Default(c)
|
||||||
obj := s.Get(loginUser)
|
obj := s.Get(loginUser)
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
"expireDate" = "Expire date"
|
"expireDate" = "Expire date"
|
||||||
"resetTraffic" = "Reset traffic"
|
"resetTraffic" = "Reset traffic"
|
||||||
"addInbound" = "Add Inbound"
|
"addInbound" = "Add Inbound"
|
||||||
|
"generalActions" = "General Actions"
|
||||||
"addTo" = "Create"
|
"addTo" = "Create"
|
||||||
"revise" = "Update"
|
"revise" = "Update"
|
||||||
"modifyInbound" = "Modify InBound"
|
"modifyInbound" = "Modify InBound"
|
||||||
@@ -138,9 +139,15 @@
|
|||||||
"resetAllTraffic" = "Reset All Inbounds Traffic"
|
"resetAllTraffic" = "Reset All Inbounds Traffic"
|
||||||
"resetAllTrafficTitle" = "Reset all inbounds traffic"
|
"resetAllTrafficTitle" = "Reset all inbounds traffic"
|
||||||
"resetAllTrafficContent" = "Are you sure to reset all inbounds traffic ?"
|
"resetAllTrafficContent" = "Are you sure to reset all inbounds traffic ?"
|
||||||
"resetAllClientTraffics" = "Reset Clients Traffic"
|
"resetInboundClientTraffics" = "Reset Clients Traffic"
|
||||||
|
"resetInboundClientTrafficTitle" = "Reset all clients traffic"
|
||||||
|
"resetInboundClientTrafficContent" = "Are you sure to reset all traffics of this inbound's clients ?"
|
||||||
|
"resetAllClientTraffics" = "Reset All Clients Traffic"
|
||||||
"resetAllClientTrafficTitle" = "Reset all clients traffic"
|
"resetAllClientTrafficTitle" = "Reset all clients traffic"
|
||||||
"resetAllClientTrafficContent" = "Are you sure to reset all traffics of this inbound's clients ?"
|
"resetAllClientTrafficContent" = "Are you sure to reset all traffics of all clients ?"
|
||||||
|
"delDepletedClients" = "Delete depleted clients"
|
||||||
|
"delDepletedClientsTitle" = "Delete depleted clients"
|
||||||
|
"delDepletedClientsContent" = "Are you sure to delete all depleted clients ?"
|
||||||
"Email" = "Email"
|
"Email" = "Email"
|
||||||
"EmailDesc" = "The Email Must Be Completely Unique"
|
"EmailDesc" = "The Email Must Be Completely Unique"
|
||||||
"setDefaultCert" = "Set cert from panel"
|
"setDefaultCert" = "Set cert from panel"
|
||||||
@@ -199,7 +206,7 @@
|
|||||||
"publicKeyPathDesc" = "Fill in an absolute path starting with '/', restart the panel to take effect"
|
"publicKeyPathDesc" = "Fill in an absolute path starting with '/', restart the panel to take effect"
|
||||||
"privateKeyPath" = "Panel certificate private key file path"
|
"privateKeyPath" = "Panel certificate private key file path"
|
||||||
"privateKeyPathDesc" = "Fill in an absolute path starting with '/', restart the panel to take effect"
|
"privateKeyPathDesc" = "Fill in an absolute path starting with '/', restart the panel to take effect"
|
||||||
"panelUrlPath" = "panel url root path"
|
"panelUrlPath" = "Panel url root path"
|
||||||
"panelUrlPathDesc" = "Must start with '/' and end with '/', restart the panel to take effect"
|
"panelUrlPathDesc" = "Must start with '/' and end with '/', restart the panel to take effect"
|
||||||
"oldUsername" = "Current Username"
|
"oldUsername" = "Current Username"
|
||||||
"currentPassword" = "Current Password"
|
"currentPassword" = "Current Password"
|
||||||
@@ -229,6 +236,8 @@
|
|||||||
"telegramNotifyTimeDesc" = "Using Crontab timing format. Restart the panel to take effect"
|
"telegramNotifyTimeDesc" = "Using Crontab timing format. Restart the panel to take effect"
|
||||||
"tgNotifyBackup" = "Database backup"
|
"tgNotifyBackup" = "Database backup"
|
||||||
"tgNotifyBackupDesc" = "Sending database backup file with report notification. Restart the panel to take effect"
|
"tgNotifyBackupDesc" = "Sending database backup file with report notification. Restart the panel to take effect"
|
||||||
|
"sessionMaxAge" = "Session maximum age"
|
||||||
|
"sessionMaxAgeDesc" = "The time that you can stay login (unit: minute)"
|
||||||
"expireTimeDiff" = "Exhaustion time threshold"
|
"expireTimeDiff" = "Exhaustion time threshold"
|
||||||
"expireTimeDiffDesc" = "Detect exhaustion before expiration (unit:day)"
|
"expireTimeDiffDesc" = "Detect exhaustion before expiration (unit:day)"
|
||||||
"trafficDiff" = "Exhaustion traffic threshold"
|
"trafficDiff" = "Exhaustion traffic threshold"
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
"expireDate" = "تاریخ انقضا"
|
"expireDate" = "تاریخ انقضا"
|
||||||
"resetTraffic" = "ریست ترافیک"
|
"resetTraffic" = "ریست ترافیک"
|
||||||
"addInbound" = "اضافه کردن سرویس"
|
"addInbound" = "اضافه کردن سرویس"
|
||||||
|
"generalActions" = "عملیات کلی"
|
||||||
"addTo" = "اضافه کردن"
|
"addTo" = "اضافه کردن"
|
||||||
"revise" = "ویرایش"
|
"revise" = "ویرایش"
|
||||||
"modifyInbound" = "ویرایش سرویس"
|
"modifyInbound" = "ویرایش سرویس"
|
||||||
@@ -138,9 +139,15 @@
|
|||||||
"resetAllTraffic" = "ریست ترافیک کل سرویس ها"
|
"resetAllTraffic" = "ریست ترافیک کل سرویس ها"
|
||||||
"resetAllTrafficTitle" = "ریست ترافیک کل سرویس ها"
|
"resetAllTrafficTitle" = "ریست ترافیک کل سرویس ها"
|
||||||
"resetAllTrafficContent" = "آیا مطمئن هستید که میخواهید تمام ترافیک سرویس ها را ریست کنید؟"
|
"resetAllTrafficContent" = "آیا مطمئن هستید که میخواهید تمام ترافیک سرویس ها را ریست کنید؟"
|
||||||
|
"resetInboundClientTraffics" = "ریست ترافیک کاربران"
|
||||||
|
"resetInboundClientTrafficTitle" = "ریست ترافیک کل کاربران"
|
||||||
|
"resetInboundClientTrafficContent" = "آیا مطمئن هستید که میخواهید تمام ترافیک کاربران این سرویس را ریست کنید؟"
|
||||||
"resetAllClientTraffics" = "ریست ترافیک کاربران"
|
"resetAllClientTraffics" = "ریست ترافیک کاربران"
|
||||||
"resetAllClientTrafficTitle" = "ریست ترافیک کل کاربران"
|
"resetAllClientTrafficTitle" = "ریست ترافیک کل کاربران"
|
||||||
"resetAllClientTrafficContent" = "آیا مطمئن هستید که میخواهید تمام ترافیک کاربران این سرویس را ریست کنید؟"
|
"resetAllClientTrafficContent" = "آیا مطمئن هستید که میخواهید تمام ترافیک کاربران را ریست کنید؟"
|
||||||
|
"delDepletedClients" = "حذف کاربران منقضی"
|
||||||
|
"delDepletedClientsTitle" = "حذف کاربران منقضی"
|
||||||
|
"delDepletedClientsContent" = "آیا مطمئن هستید مه میخواهید تمامی کاربران منقضی شده را حذف کنید؟"
|
||||||
"Email" = "ایمیل"
|
"Email" = "ایمیل"
|
||||||
"EmailDesc" = "ایمیل باید کاملا منحصر به فرد باشد"
|
"EmailDesc" = "ایمیل باید کاملا منحصر به فرد باشد"
|
||||||
"setDefaultCert" = "استفاده از گواهی پنل"
|
"setDefaultCert" = "استفاده از گواهی پنل"
|
||||||
@@ -229,6 +236,8 @@
|
|||||||
"telegramNotifyTimeDesc" = "از فرمت زمان بندی لینوکس استفاده کنید . پنل را مجدداً راه اندازی کنید تا اعمال شود"
|
"telegramNotifyTimeDesc" = "از فرمت زمان بندی لینوکس استفاده کنید . پنل را مجدداً راه اندازی کنید تا اعمال شود"
|
||||||
"tgNotifyBackup" = "پشتیبان گیری از پایگاه داده"
|
"tgNotifyBackup" = "پشتیبان گیری از پایگاه داده"
|
||||||
"tgNotifyBackupDesc" = "ارسال کپی فایل پایگاه داده به همراه گزارش دوره ای"
|
"tgNotifyBackupDesc" = "ارسال کپی فایل پایگاه داده به همراه گزارش دوره ای"
|
||||||
|
"sessionMaxAge" = "بیشینه زمان جلسه وب"
|
||||||
|
"sessionMaxAgeDesc" = "بیشینه زمانی که میتوانید لاگین بمانید (واحد: دقیقه)"
|
||||||
"expireTimeDiff" = "آستانه زمان باقی مانده"
|
"expireTimeDiff" = "آستانه زمان باقی مانده"
|
||||||
"expireTimeDiffDesc" = "فاصله زمانی هشدار تا رسیدن به زمان انقضا (واحد: روز)"
|
"expireTimeDiffDesc" = "فاصله زمانی هشدار تا رسیدن به زمان انقضا (واحد: روز)"
|
||||||
"trafficDiff" = "آستانه ترافیک باقی مانده"
|
"trafficDiff" = "آستانه ترافیک باقی مانده"
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
"expireDate" = "到期时间"
|
"expireDate" = "到期时间"
|
||||||
"resetTraffic" = "重置流量"
|
"resetTraffic" = "重置流量"
|
||||||
"addInbound" = "添加入"
|
"addInbound" = "添加入"
|
||||||
|
"generalActions" = "通用操作"
|
||||||
"addTo" = "添加"
|
"addTo" = "添加"
|
||||||
"revise" = "修改"
|
"revise" = "修改"
|
||||||
"modifyInbound" = "修改入站"
|
"modifyInbound" = "修改入站"
|
||||||
@@ -138,9 +139,15 @@
|
|||||||
"resetAllTraffic" = "重置所有入站流量"
|
"resetAllTraffic" = "重置所有入站流量"
|
||||||
"resetAllTrafficTitle" = "重置所有入站流量"
|
"resetAllTrafficTitle" = "重置所有入站流量"
|
||||||
"resetAllTrafficContent" = "您确定要重置所有入站流量吗?"
|
"resetAllTrafficContent" = "您确定要重置所有入站流量吗?"
|
||||||
"resetAllClientTraffics" = "重置客户端流量"
|
"resetInboundClientTraffics" = "重置客户端流量"
|
||||||
|
"resetInboundClientTrafficTitle" = "重置所有客户端流量"
|
||||||
|
"resetInboundClientTrafficContent" = "您确定要重置此入站客户端的所有流量吗?"
|
||||||
|
"resetAllClientTraffics" = "重置所有客户端流量"
|
||||||
"resetAllClientTrafficTitle" = "重置所有客户端流量"
|
"resetAllClientTrafficTitle" = "重置所有客户端流量"
|
||||||
"resetAllClientTrafficContent" = "您确定要重置此入站客户端的所有流量吗?"
|
"resetAllClientTrafficContent" = "你确定要重置所有客户端的所有流量吗?"
|
||||||
|
"delDepletedClients" = "删除耗尽的客户端"
|
||||||
|
"delDepletedClientsTitle" = "删除耗尽的客户"
|
||||||
|
"delDepletedClientsContent" = "你确定要删除所有耗尽的客户端吗?"
|
||||||
"Email" = "电子邮件"
|
"Email" = "电子邮件"
|
||||||
"EmailDesc" = "电子邮件必须完全唯"
|
"EmailDesc" = "电子邮件必须完全唯"
|
||||||
"setDefaultCert" = "从面板设置证书"
|
"setDefaultCert" = "从面板设置证书"
|
||||||
@@ -229,6 +236,8 @@
|
|||||||
"telegramNotifyTimeDesc" = "采用Crontab定时格式,重启面板生效"
|
"telegramNotifyTimeDesc" = "采用Crontab定时格式,重启面板生效"
|
||||||
"tgNotifyBackup" = "数据库备份"
|
"tgNotifyBackup" = "数据库备份"
|
||||||
"tgNotifyBackupDesc" = "正在发送数据库备份文件和报告通知。重启面板生效"
|
"tgNotifyBackupDesc" = "正在发送数据库备份文件和报告通知。重启面板生效"
|
||||||
|
"sessionMaxAge" = "会话最大年龄"
|
||||||
|
"sessionMaxAgeDesc" = "您可以保持登录状态的时间(单位:分钟)"
|
||||||
"expireTimeDiff" = "耗尽时间阈值"
|
"expireTimeDiff" = "耗尽时间阈值"
|
||||||
"expireTimeDiffDesc" = "到期前检测耗尽(单位:天)"
|
"expireTimeDiffDesc" = "到期前检测耗尽(单位:天)"
|
||||||
"trafficDiff" = "耗尽流量阈值"
|
"trafficDiff" = "耗尽流量阈值"
|
||||||
|
|||||||
Reference in New Issue
Block a user