API - Add Client to inbounds

This commit is contained in:
Javad Tinatpak 2024-08-06 13:39:37 +03:30
parent d8d9c64847
commit e299365c62
4 changed files with 158 additions and 0 deletions

View file

@ -467,6 +467,7 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi
| `POST` | `"/clientIps/:email"` | Client Ip address | | `POST` | `"/clientIps/:email"` | Client Ip address |
| `POST` | `"/clearClientIps/:email"` | Clear Client Ip address | | `POST` | `"/clearClientIps/:email"` | Clear Client Ip address |
| `POST` | `"/addClient"` | Add Client to inbound | | `POST` | `"/addClient"` | Add Client to inbound |
| `POST` | `"/addClientInbounds"` | Add Client to inbounds |
| `POST` | `"/:id/delClient/:clientId"` | Delete Client by clientId\* | | `POST` | `"/:id/delClient/:clientId"` | Delete Client by clientId\* |
| `POST` | `"/updateClient/:clientId"` | Update Client by clientId\* | | `POST` | `"/updateClient/:clientId"` | Update Client by clientId\* |
| `POST` | `"/:id/resetClientTraffic/:email"` | Reset Client's Traffic | | `POST` | `"/:id/resetClientTraffic/:email"` | Reset Client's Traffic |

View file

@ -40,6 +40,7 @@ func (a *APIController) initRouter(g *gin.RouterGroup) {
{"POST", "/clientIps/:email", a.inboundController.getClientIps}, {"POST", "/clientIps/:email", a.inboundController.getClientIps},
{"POST", "/clearClientIps/:email", a.inboundController.clearClientIps}, {"POST", "/clearClientIps/:email", a.inboundController.clearClientIps},
{"POST", "/addClient", a.inboundController.addInboundClient}, {"POST", "/addClient", a.inboundController.addInboundClient},
{"POST", "/addClientInbounds", a.inboundController.addClientToMultipleInbounds},
{"POST", "/:id/delClient/:clientId", a.inboundController.delInboundClient}, {"POST", "/:id/delClient/:clientId", a.inboundController.delInboundClient},
{"POST", "/updateClient/:clientId", a.inboundController.updateInboundClient}, {"POST", "/updateClient/:clientId", a.inboundController.updateInboundClient},
{"POST", "/:id/resetClientTraffic/:email", a.inboundController.resetClientTraffic}, {"POST", "/:id/resetClientTraffic/:email", a.inboundController.resetClientTraffic},

View file

@ -17,6 +17,12 @@ type InboundController struct {
xrayService service.XrayService xrayService service.XrayService
} }
type AddClientPayload struct {
Id int `json:"id"`
Settings string `json:"settings"`
InboundIds []int `json:"inboundIds"`
}
func NewInboundController(g *gin.RouterGroup) *InboundController { func NewInboundController(g *gin.RouterGroup) *InboundController {
a := &InboundController{} a := &InboundController{}
a.initRouter(g) a.initRouter(g)
@ -33,6 +39,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
g.POST("/clientIps/:email", a.getClientIps) g.POST("/clientIps/:email", a.getClientIps)
g.POST("/clearClientIps/:email", a.clearClientIps) g.POST("/clearClientIps/:email", a.clearClientIps)
g.POST("/addClient", a.addInboundClient) g.POST("/addClient", a.addInboundClient)
g.POST("/addClientInbounds", a.addClientToMultipleInbounds)
g.POST("/:id/delClient/:clientId", a.delInboundClient) g.POST("/:id/delClient/:clientId", a.delInboundClient)
g.POST("/updateClient/:clientId", a.updateInboundClient) g.POST("/updateClient/:clientId", a.updateInboundClient)
g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
@ -190,6 +197,47 @@ func (a *InboundController) addInboundClient(c *gin.Context) {
} }
} }
func (a *InboundController) addClientToMultipleInbounds(c *gin.Context) {
var payload AddClientPayload
if err := c.ShouldBindJSON(&payload); err != nil {
jsonMsg(c, "Invalid request payload", err)
return
}
data := &model.Inbound{
Id: payload.Id,
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, err := a.inboundService.AddClientToMultipleInbounds(data, payload.InboundIds)
if err != nil {
jsonMsg(c, "Something went wrong!", err)
return
}
jsonMsg(c, "Client(s) added to multiple inbounds", nil)
if needRestart {
a.xrayService.SetToNeedRestart()
}
}
func (a *InboundController) delInboundClient(c *gin.Context) { func (a *InboundController) delInboundClient(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id")) id, err := strconv.Atoi(c.Param("id"))
if err != nil { if err != nil {

View file

@ -510,6 +510,114 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) {
return needRestart, tx.Save(oldInbound).Error return needRestart, tx.Save(oldInbound).Error
} }
func (s *InboundService) AddClientToMultipleInbounds(data *model.Inbound, inboundIds []int) (bool, error) {
clients, err := s.GetClients(data)
if err != nil {
return false, err
}
var settings map[string]interface{}
err = json.Unmarshal([]byte(data.Settings), &settings)
if err != nil {
return false, err
}
interfaceClients := settings["clients"].([]interface{})
needRestart := false
db := database.GetDB()
tx := db.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
for _, inboundId := range inboundIds {
oldInbound, err := s.GetInbound(inboundId)
if err != nil {
return false, err
}
for _, client := range interfaceClients {
clientMap, ok := client.(map[string]interface{})
if !ok {
return false, common.NewError("Invalid client format")
}
for _, cl := range clients {
newEmail := cl.Email + "_" + strconv.Itoa(inboundId)
existEmail, err := s.checkEmailsExistForClients([]model.Client{{Email: newEmail}})
if err != nil {
return false, err
}
if existEmail != "" {
return false, common.NewError("Duplicate email:", existEmail)
}
clientMap["email"] = newEmail
}
}
var oldSettings map[string]interface{}
err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings)
if err != nil {
return false, err
}
oldClients := oldSettings["clients"].([]interface{})
oldClients = append(oldClients, interfaceClients...)
oldSettings["clients"] = oldClients
newSettings, err := json.MarshalIndent(oldSettings, "", " ")
if err != nil {
return false, err
}
oldInbound.Settings = string(newSettings)
s.xrayApi.Init(p.GetAPIPort())
for _, client := range clients {
client.Email = client.Email + "_" + strconv.Itoa(inboundId)
if len(client.Email) > 0 {
s.AddClientStat(tx, inboundId, &client)
if client.Enable {
cipher := ""
if oldInbound.Protocol == "shadowsocks" {
cipher = oldSettings["method"].(string)
}
err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
"email": client.Email,
"id": client.ID,
"flow": client.Flow,
"password": client.Password,
"cipher": cipher,
})
if err1 != nil {
logger.Debug("Error in adding client by api:", err1)
needRestart = true
} else {
logger.Debug("Client added by api:", client.Email)
}
}
} else {
needRestart = true
}
}
if err := tx.Save(oldInbound).Error; err != nil {
return false, err
}
s.xrayApi.Close()
}
return needRestart, nil
}
func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool, error) { func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool, error) {
oldInbound, err := s.GetInbound(inboundId) oldInbound, err := s.GetInbound(inboundId)
if err != nil { if err != nil {