mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-04-14 19:45:47 +00:00
## Critical Fixes
### 1. DATA LOSS: 5 functions discard all other clients when updating one
Functions affected:
- SetClientTelegramUserID
- ToggleClientEnableByEmail
- ResetClientIpLimitByEmail
- ResetClientExpiryTimeByEmail
- ResetClientTrafficLimitByEmail
All five built a `newClients` slice by only appending the client
matching the target email, then replaced the entire client list.
Every other client in the inbound was silently deleted.
Fix: update client in-place with break instead of building new slice.
### 2. DATA LOSS: ResetSettings never deletes user credentials
ResetSettings() called `.Where("1 = 1").Error` instead of
`.Delete(model.User{}).Error`. The reset command did nothing to users.
### 3. SECURITY: WebSocket CheckOrigin allows cross-origin hijacking
The fallback `(originHost == "" || requestHost == "")` accepted
any origin with a missing host component. Removed the fallback and
added proper host normalization for IPv6/ports.
### 4. GRACEFUL SHUTDOWN: Server.Stop() uses cancelled context
s.cancel() was called before s.httpServer.Shutdown(s.ctx), making
the context already-done. Shutdown returned immediately (forced kill)
instead of waiting 10 seconds. Moved s.cancel() to end and used
context.WithTimeout(10s) for shutdown. Same fix applied to sub.go.
## Medium Fixes
### 5. Wrong success messages on error paths (~11 endpoints)
When validation failed, endpoints returned messages like
"inboundUpdateSuccess" alongside the error. Fixed to use
"somethingWentWrong" for all error paths.
### 6. resetAllTraffics/resetAllClientTraffics trigger restart on error
SetToNeedRestart() was called in else branch that ran even on failure.
Restructured to only call after confirming success.
### 7. disableInvalidClients has duplicate unreachable error check
Same "User %s not found" string check was nested twice.
Removed the inner duplicate.
### 8. DelInbound logs uninitialized tag variable
The else branch logged empty tag variable instead of actual inbound id.
### 9. check_cpu_usage.go index-out-of-range panic
cpu.Percent() can return empty slice. Added len(percent) > 0 guard.
### 10. Dead code: cron.Remove(entry) on never-added entry
var entry cron.EntryID defaults to 0; cron.Remove(0) is a no-op.
### 11. checkEmailExistForInbound duplicates checkEmailsExistForClients
Refactored to delegate to existing function instead of reimplementing.
40 lines
1.1 KiB
Go
40 lines
1.1 KiB
Go
package job
|
|
|
|
import (
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/mhsanaei/3x-ui/v2/web/service"
|
|
|
|
"github.com/shirou/gopsutil/v4/cpu"
|
|
)
|
|
|
|
// CheckCpuJob monitors CPU usage and sends Telegram notifications when usage exceeds the configured threshold.
|
|
type CheckCpuJob struct {
|
|
tgbotService service.Tgbot
|
|
settingService service.SettingService
|
|
}
|
|
|
|
// NewCheckCpuJob creates a new CPU monitoring job instance.
|
|
func NewCheckCpuJob() *CheckCpuJob {
|
|
return new(CheckCpuJob)
|
|
}
|
|
|
|
// Run checks CPU usage over the last minute and sends a Telegram alert if it exceeds the threshold.
|
|
func (j *CheckCpuJob) Run() {
|
|
threshold, err := j.settingService.GetTgCpu()
|
|
if err != nil || threshold <= 0 {
|
|
// If threshold cannot be retrieved or is not set, skip sending notifications
|
|
return
|
|
}
|
|
|
|
// get latest status of server
|
|
percent, err := cpu.Percent(1*time.Minute, false)
|
|
if err == nil && len(percent) > 0 && percent[0] > float64(threshold) {
|
|
msg := j.tgbotService.I18nBot("tgbot.messages.cpuThreshold",
|
|
"Percent=="+strconv.FormatFloat(percent[0], 'f', 2, 64),
|
|
"Threshold=="+strconv.Itoa(threshold))
|
|
|
|
j.tgbotService.SendMsgToTgbotAdmins(msg)
|
|
}
|
|
}
|