mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-09-10 20:26:19 +00:00
API - Update Client to inbounds
This commit is contained in:
parent
e299365c62
commit
b3e1052c61
4 changed files with 199 additions and 3 deletions
|
@ -459,7 +459,7 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi
|
|||
| `GET` | `"/list"` | Get all inbounds |
|
||||
| `GET` | `"/get/:id"` | Get inbound with inbound.id |
|
||||
| `GET` | `"/getClientTraffics/:email"` | Get Client Traffics with email |
|
||||
| `GET` | `"/getClientTrafficsById/:id"` | Get client's traffic By ID |
|
||||
| `GET` | `"/getClientTrafficsById/:id"` | Get client's traffic By ID |
|
||||
| `GET` | `"/createbackup"` | Telegram bot sends backup to admins |
|
||||
| `POST` | `"/add"` | Add inbound |
|
||||
| `POST` | `"/del/:id"` | Delete Inbound |
|
||||
|
@ -470,6 +470,7 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi
|
|||
| `POST` | `"/addClientInbounds"` | Add Client to inbounds |
|
||||
| `POST` | `"/:id/delClient/:clientId"` | Delete Client by clientId\* |
|
||||
| `POST` | `"/updateClient/:clientId"` | Update Client by clientId\* |
|
||||
| `POST` | `"/updateClientInbounds/:subId"` | Update Client by subId\* |
|
||||
| `POST` | `"/:id/resetClientTraffic/:email"` | Reset Client's Traffic |
|
||||
| `POST` | `"/resetAllTraffics"` | Reset traffics of all inbounds |
|
||||
| `POST` | `"/resetAllClientTraffics/:id"` | Reset traffics of all clients in an inbound |
|
||||
|
|
|
@ -43,6 +43,7 @@ func (a *APIController) initRouter(g *gin.RouterGroup) {
|
|||
{"POST", "/addClientInbounds", a.inboundController.addClientToMultipleInbounds},
|
||||
{"POST", "/:id/delClient/:clientId", a.inboundController.delInboundClient},
|
||||
{"POST", "/updateClient/:clientId", a.inboundController.updateInboundClient},
|
||||
{"POST", "/updateClientInbounds/:subId", a.inboundController.updateClientInMultipleInbounds},
|
||||
{"POST", "/:id/resetClientTraffic/:email", a.inboundController.resetClientTraffic},
|
||||
{"POST", "/resetAllTraffics", a.inboundController.resetAllTraffics},
|
||||
{"POST", "/resetAllClientTraffics/:id", a.inboundController.resetAllClientTraffics},
|
||||
|
|
|
@ -18,7 +18,6 @@ type InboundController struct {
|
|||
}
|
||||
|
||||
type AddClientPayload struct {
|
||||
Id int `json:"id"`
|
||||
Settings string `json:"settings"`
|
||||
InboundIds []int `json:"inboundIds"`
|
||||
}
|
||||
|
@ -42,6 +41,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
|
|||
g.POST("/addClientInbounds", a.addClientToMultipleInbounds)
|
||||
g.POST("/:id/delClient/:clientId", a.delInboundClient)
|
||||
g.POST("/updateClient/:clientId", a.updateInboundClient)
|
||||
g.POST("/updateClientInbounds/:subId", a.updateClientInMultipleInbounds)
|
||||
g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
|
||||
g.POST("/resetAllTraffics", a.resetAllTraffics)
|
||||
g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics)
|
||||
|
@ -206,7 +206,6 @@ func (a *InboundController) addClientToMultipleInbounds(c *gin.Context) {
|
|||
}
|
||||
|
||||
data := &model.Inbound{
|
||||
Id: payload.Id,
|
||||
Settings: payload.Settings,
|
||||
}
|
||||
|
||||
|
@ -236,6 +235,45 @@ func (a *InboundController) addClientToMultipleInbounds(c *gin.Context) {
|
|||
}
|
||||
|
||||
|
||||
func (a *InboundController) updateClientInMultipleInbounds(c *gin.Context) {
|
||||
var payload AddClientPayload
|
||||
subId := c.Param("subId")
|
||||
|
||||
if err := c.ShouldBindJSON(&payload); err != nil {
|
||||
jsonMsg(c, "Invalid request payload", err)
|
||||
return
|
||||
}
|
||||
|
||||
data := &model.Inbound{
|
||||
Settings: payload.Settings,
|
||||
}
|
||||
|
||||
// If no specific inbound IDs are provided, add to all inbounds
|
||||
if len(payload.InboundIds) == 0 {
|
||||
allInbounds, err := a.inboundService.GetAllInbounds()
|
||||
if err != nil {
|
||||
jsonMsg(c, "Could not retrieve inbounds", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, inbound := range allInbounds {
|
||||
payload.InboundIds = append(payload.InboundIds, inbound.Id)
|
||||
}
|
||||
}
|
||||
|
||||
needRestart := true
|
||||
|
||||
needRestart, err = a.inboundService.UpdateClientInMultipleInbounds(data, subId, payload.InboundIds)
|
||||
if err != nil {
|
||||
jsonMsg(c, "Something went wrong!", err)
|
||||
return
|
||||
}
|
||||
jsonMsg(c, "Client updated in multiple inbounds", nil)
|
||||
if needRestart {
|
||||
a.xrayService.SetToNeedRestart()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (a *InboundController) delInboundClient(c *gin.Context) {
|
||||
|
|
|
@ -838,6 +838,162 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
|
|||
return needRestart, tx.Save(oldInbound).Error
|
||||
}
|
||||
|
||||
func (s *InboundService) UpdateClientInMultipleInbounds(data *model.Inbound, subId string, inboundIds []int) (bool, error) {
|
||||
var needRestart bool
|
||||
|
||||
for _, inboundId := range inboundIds {
|
||||
inbound, err := s.GetInbound(inboundId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
clients, err := s.GetClients(data)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var settings map[string]interface{}
|
||||
err = json.Unmarshal([]byte(inbound.Settings), &settings)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
interfaceClients := settings["clients"].([]interface{})
|
||||
|
||||
oldClients, err := s.GetClients(inbound)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
oldEmail := ""
|
||||
newClientsubId := ""
|
||||
clientIndex := -1
|
||||
for index, oldClient := range oldClients {
|
||||
oldClientsubId := ""
|
||||
if inbound.Protocol == "trojan" {
|
||||
oldClientsubId = oldClient.SubID
|
||||
newClientsubId = clients[0].SubID
|
||||
} else if inbound.Protocol == "shadowsocks" {
|
||||
oldClientsubId = oldClient.SubID
|
||||
newClientsubId = clients[0].SubID
|
||||
} else {
|
||||
oldClientsubId = oldClient.SubID
|
||||
newClientsubId = clients[0].SubID
|
||||
}
|
||||
if subId == oldClientsubId {
|
||||
oldEmail = oldClient.Email
|
||||
clientIndex = index
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if newClientsubId == "" || clientIndex == -1 {
|
||||
return false, common.NewError("empty client SubID")
|
||||
}
|
||||
|
||||
if len(clients[0].Email) > 0 && clients[0].Email != oldEmail {
|
||||
existEmail, err := s.checkEmailsExistForClients(clients)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if existEmail != "" {
|
||||
return false, common.NewError("Duplicate email:", existEmail)
|
||||
}
|
||||
}
|
||||
|
||||
var oldSettings map[string]interface{}
|
||||
err = json.Unmarshal([]byte(inbound.Settings), &oldSettings)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
settingsClients := oldSettings["clients"].([]interface{})
|
||||
settingsClients[clientIndex] = interfaceClients[0]
|
||||
oldSettings["clients"] = settingsClients
|
||||
|
||||
newSettings, err := json.MarshalIndent(oldSettings, "", " ")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
inbound.Settings = string(newSettings)
|
||||
db := database.GetDB()
|
||||
tx := db.Begin()
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
} else {
|
||||
tx.Commit()
|
||||
}
|
||||
}()
|
||||
|
||||
if len(clients[0].Email) > 0 {
|
||||
if len(oldEmail) > 0 {
|
||||
err = s.UpdateClientStat(tx, oldEmail, &clients[0])
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = s.UpdateClientIPs(tx, oldEmail, clients[0].Email)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
} else {
|
||||
s.AddClientStat(tx, inbound.Id, &clients[0])
|
||||
}
|
||||
} else {
|
||||
err = s.DelClientStat(tx, oldEmail)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = s.DelClientIPs(tx, oldEmail)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(oldEmail) > 0 {
|
||||
s.xrayApi.Init(p.GetAPIPort())
|
||||
err1 := s.xrayApi.RemoveUser(inbound.Tag, oldEmail)
|
||||
if err1 == nil {
|
||||
logger.Debug("Old client deleted by api:", clients[0].Email)
|
||||
} else {
|
||||
logger.Debug("Error in deleting client by api:", err1)
|
||||
needRestart = true
|
||||
}
|
||||
if clients[0].Enable {
|
||||
cipher := ""
|
||||
if inbound.Protocol == "shadowsocks" {
|
||||
cipher = oldSettings["method"].(string)
|
||||
}
|
||||
err1 := s.xrayApi.AddUser(string(inbound.Protocol), inbound.Tag, map[string]interface{}{
|
||||
"email": clients[0].Email,
|
||||
"id": clients[0].ID,
|
||||
"flow": clients[0].Flow,
|
||||
"password": clients[0].Password,
|
||||
"cipher": cipher,
|
||||
})
|
||||
if err1 == nil {
|
||||
logger.Debug("Client edited by api:", clients[0].Email)
|
||||
} else {
|
||||
logger.Debug("Error in adding client by api:", err1)
|
||||
needRestart = true
|
||||
}
|
||||
}
|
||||
s.xrayApi.Close()
|
||||
} else {
|
||||
logger.Debug("Client old email not found")
|
||||
needRestart = true
|
||||
}
|
||||
|
||||
if err := tx.Save(inbound).Error; err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
return needRestart, nil
|
||||
}
|
||||
|
||||
|
||||
func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) (error, bool) {
|
||||
var err error
|
||||
db := database.GetDB()
|
||||
|
|
Loading…
Reference in a new issue