{{ i18n "comment" }} |
diff --git a/web/html/modals/inbound_modal.html b/web/html/modals/inbound_modal.html
index b77e74e2..60af57cb 100644
--- a/web/html/modals/inbound_modal.html
+++ b/web/html/modals/inbound_modal.html
@@ -1,9 +1,7 @@
{{define "modals/inboundModal"}}
-
+
{{template "form/inbound"}}
-{{end}}
+{{end}}
\ No newline at end of file
diff --git a/web/html/modals/xray_rule_modal.html b/web/html/modals/xray_rule_modal.html
index 336a9d81..32a3f80c 100644
--- a/web/html/modals/xray_rule_modal.html
+++ b/web/html/modals/xray_rule_modal.html
@@ -1,11 +1,6 @@
{{define "modals/ruleModal"}}
-
-
- [[ dm ]]
-
-
@@ -123,7 +118,6 @@
confirm: null,
rule: {
type: "field",
- domainMatcher: "",
domain: "",
ip: "",
port: "",
@@ -157,7 +151,6 @@
this.confirm = confirm;
this.visible = true;
if (isEdit) {
- this.rule.domainMatcher = rule.domainMatcher;
this.rule.domain = rule.domain ? rule.domain.join(',') : [];
this.rule.ip = rule.ip ? rule.ip.join(',') : [];
this.rule.port = rule.port;
@@ -172,7 +165,6 @@
this.rule.balancerTag = rule.balancerTag ? rule.balancerTag : "";
} else {
this.rule = {
- domainMatcher: "",
domain: "",
ip: "",
port: "",
@@ -214,7 +206,6 @@
rule = {};
newRule = {};
rule.type = "field";
- rule.domainMatcher = value.domainMatcher;
rule.domain = value.domain.length > 0 ? value.domain.split(',') : [];
rule.ip = value.ip.length > 0 ? value.ip.split(',') : [];
rule.port = value.port;
diff --git a/web/service/inbound.go b/web/service/inbound.go
index 1be873ac..2f342dd0 100644
--- a/web/service/inbound.go
+++ b/web/service/inbound.go
@@ -359,6 +359,7 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
var oldSettings map[string]any
_ = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings)
emailToCreated := map[string]int64{}
+ emailToUpdated := map[string]int64{}
if oldSettings != nil {
if oc, ok := oldSettings["clients"].([]any); ok {
for _, it := range oc {
@@ -370,6 +371,12 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
case int64:
emailToCreated[email] = v
}
+ switch v := m["updated_at"].(type) {
+ case float64:
+ emailToUpdated[email] = int64(v)
+ case int64:
+ emailToUpdated[email] = v
+ }
}
}
}
@@ -389,7 +396,12 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
m["created_at"] = now
}
}
- m["updated_at"] = now
+ // Preserve client's updated_at if present; do not bump on parent inbound update
+ if _, hasUpdated := m["updated_at"]; !hasUpdated {
+ if v, ok4 := emailToUpdated[email]; ok4 && v > 0 {
+ m["updated_at"] = v
+ }
+ }
nSlice[i] = m
}
}
@@ -978,6 +990,7 @@ func (s *InboundService) addClientTraffic(tx *gorm.DB, traffics []*xray.ClientTr
// Add user in onlineUsers array on traffic
if traffics[traffic_index].Up+traffics[traffic_index].Down > 0 {
onlineClients = append(onlineClients, traffics[traffic_index].Email)
+ dbClientTraffics[dbTraffic_index].LastOnline = time.Now().UnixMilli()
}
break
}
@@ -2198,6 +2211,20 @@ func (s *InboundService) GetOnlineClients() []string {
return p.GetOnlineClients()
}
+func (s *InboundService) GetClientsLastOnline() (map[string]int64, error) {
+ db := database.GetDB()
+ var rows []xray.ClientTraffic
+ err := db.Model(&xray.ClientTraffic{}).Select("email, last_online").Find(&rows).Error
+ if err != nil && err != gorm.ErrRecordNotFound {
+ return nil, err
+ }
+ result := make(map[string]int64, len(rows))
+ for _, r := range rows {
+ result[r.Email] = r.LastOnline
+ }
+ return result, nil
+}
+
func (s *InboundService) FilterAndSortClientEmails(emails []string) ([]string, []string, error) {
db := database.GetDB()
diff --git a/web/service/server.go b/web/service/server.go
index 2dc83d77..3078e88b 100644
--- a/web/service/server.go
+++ b/web/service/server.go
@@ -871,3 +871,53 @@ func (s *ServerService) GetNewEchCert(sni string) (interface{}, error) {
"echConfigList": configList,
}, nil
}
+
+type AuthBlock struct {
+ Label string `json:"label"`
+ Decryption string `json:"decryption"`
+ Encryption string `json:"encryption"`
+}
+
+func (s *ServerService) GetNewVlessEnc() (any, error) {
+ cmd := exec.Command(xray.GetBinaryPath(), "vlessenc")
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ if err := cmd.Run(); err != nil {
+ return nil, err
+ }
+
+ lines := strings.Split(out.String(), "\n")
+
+ var blocks []AuthBlock
+ var current *AuthBlock
+
+ for _, line := range lines {
+ line = strings.TrimSpace(line)
+ if strings.HasPrefix(line, "Authentication:") {
+ if current != nil {
+ blocks = append(blocks, *current)
+ }
+ current = &AuthBlock{Label: strings.TrimSpace(strings.TrimPrefix(line, "Authentication:"))}
+ } else if strings.HasPrefix(line, `"decryption"`) || strings.HasPrefix(line, `"encryption"`) {
+ parts := strings.SplitN(line, ":", 2)
+ if len(parts) == 2 && current != nil {
+ key := strings.Trim(parts[0], `" `)
+ val := strings.Trim(parts[1], `" `)
+ switch key {
+ case "decryption":
+ current.Decryption = val
+ case "encryption":
+ current.Encryption = val
+ }
+ }
+ }
+ }
+
+ if current != nil {
+ blocks = append(blocks, *current)
+ }
+
+ return map[string]any{
+ "auths": blocks,
+ }, nil
+}
diff --git a/web/translation/translate.ar_EG.toml b/web/translation/translate.ar_EG.toml
index 9ff72316..488da92c 100644
--- a/web/translation/translate.ar_EG.toml
+++ b/web/translation/translate.ar_EG.toml
@@ -50,6 +50,7 @@
"fail" = "فشل"
"comment" = "تعليق"
"success" = "تم بنجاح"
+"lastOnline" = "آخر متصل"
"getVersion" = "جيب النسخة"
"install" = "تثبيت"
"clients" = "عملاء"
@@ -274,6 +275,7 @@
"trafficGetError" = "خطأ في الحصول على حركات المرور"
"getNewX25519CertError" = "حدث خطأ أثناء الحصول على شهادة X25519."
"getNewmldsa65Error" = "حدث خطاء في الحصول على mldsa65."
+"getNewVlessEncError" = "حدث خطأ أثناء الحصول على VlessEnc."
[pages.inbounds.stream.general]
"request" = "طلب"
diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml
index 7d54ef74..f7791860 100644
--- a/web/translation/translate.en_US.toml
+++ b/web/translation/translate.en_US.toml
@@ -50,6 +50,7 @@
"fail" = "Failed"
"comment" = "Comment"
"success" = "Successfully"
+"lastOnline" = "Last Online"
"getVersion" = "Get Version"
"install" = "Install"
"clients" = "Clients"
@@ -274,6 +275,7 @@
"trafficGetError" = "Error getting traffics."
"getNewX25519CertError" = "Error while obtaining the X25519 certificate."
"getNewmldsa65Error" = "Error while obtaining mldsa65."
+"getNewVlessEncError" = "Error while obtaining VlessEnc."
[pages.inbounds.stream.general]
"request" = "Request"
diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml
index 9d4c28b4..813597e4 100644
--- a/web/translation/translate.es_ES.toml
+++ b/web/translation/translate.es_ES.toml
@@ -50,6 +50,7 @@
"fail" = "Falló"
"comment" = "Comentario"
"success" = "Éxito"
+"lastOnline" = "Última conexión"
"getVersion" = "Obtener versión"
"install" = "Instalar"
"clients" = "Clientes"
@@ -274,6 +275,7 @@
"trafficGetError" = "Error al obtener los tráficos"
"getNewX25519CertError" = "Error al obtener el certificado X25519."
"getNewmldsa65Error" = "Error al obtener el certificado mldsa65."
+"getNewVlessEncError" = "Error al obtener el certificado VlessEnc."
[pages.inbounds.stream.general]
"request" = "Pedido"
diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml
index 82fb6043..b77e753c 100644
--- a/web/translation/translate.fa_IR.toml
+++ b/web/translation/translate.fa_IR.toml
@@ -50,6 +50,7 @@
"fail" = "ناموفق"
"comment" = "توضیحات"
"success" = "موفق"
+"lastOnline" = "آخرین فعالیت"
"getVersion" = "دریافت نسخه"
"install" = "نصب"
"clients" = "کاربران"
@@ -274,6 +275,7 @@
"trafficGetError" = "خطا در دریافت ترافیکها"
"getNewX25519CertError" = "خطا در دریافت گواهی X25519."
"getNewmldsa65Error" = "خطا در دریافت گواهی mldsa65."
+"getNewVlessEncError" = "خطا در دریافت گواهی VlessEnc."
[pages.inbounds.stream.general]
"request" = "درخواست"
diff --git a/web/translation/translate.id_ID.toml b/web/translation/translate.id_ID.toml
index a2429b82..441debd5 100644
--- a/web/translation/translate.id_ID.toml
+++ b/web/translation/translate.id_ID.toml
@@ -50,6 +50,7 @@
"fail" = "Gagal"
"comment" = "Komentar"
"success" = "Berhasil"
+"lastOnline" = "Terakhir online"
"getVersion" = "Dapatkan Versi"
"install" = "Instal"
"clients" = "Klien"
@@ -274,6 +275,7 @@
"trafficGetError" = "Gagal mendapatkan data lalu lintas"
"getNewX25519CertError" = "Terjadi kesalahan saat mendapatkan sertifikat X25519."
"getNewmldsa65Error" = "Terjadi kesalahan saat mendapatkan sertifikat mldsa65."
+"getNewVlessEncError" = "Terjadi kesalahan saat mendapatkan sertifikat VlessEnc."
[pages.inbounds.stream.general]
"request" = "Permintaan"
diff --git a/web/translation/translate.ja_JP.toml b/web/translation/translate.ja_JP.toml
index 17c31028..e9d75bde 100644
--- a/web/translation/translate.ja_JP.toml
+++ b/web/translation/translate.ja_JP.toml
@@ -50,6 +50,7 @@
"fail" = "失敗"
"comment" = "コメント"
"success" = "成功"
+"lastOnline" = "最終オンライン"
"getVersion" = "バージョン取得"
"install" = "インストール"
"clients" = "クライアント"
@@ -274,6 +275,7 @@
"trafficGetError" = "トラフィックの取得中にエラーが発生しました"
"getNewX25519CertError" = "X25519証明書の取得中にエラーが発生しました。"
"getNewmldsa65Error" = "mldsa65証明書の取得中にエラーが発生しました。"
+"getNewVlessEncError" = "VlessEnc証明書の取得中にエラーが発生しました。"
[pages.inbounds.stream.general]
"request" = "リクエスト"
diff --git a/web/translation/translate.pt_BR.toml b/web/translation/translate.pt_BR.toml
index 3e83d009..9cc16826 100644
--- a/web/translation/translate.pt_BR.toml
+++ b/web/translation/translate.pt_BR.toml
@@ -50,6 +50,7 @@
"fail" = "Falhou"
"comment" = "Comentário"
"success" = "Com Sucesso"
+"lastOnline" = "Última vez online"
"getVersion" = "Obter Versão"
"install" = "Instalar"
"clients" = "Clientes"
@@ -274,6 +275,7 @@
"trafficGetError" = "Erro ao obter tráfegos"
"getNewX25519CertError" = "Erro ao obter o certificado X25519."
"getNewmldsa65Error" = "Erro ao obter o certificado mldsa65."
+"getNewVlessEncError" = "Erro ao obter o certificado VlessEnc."
[pages.inbounds.stream.general]
"request" = "Requisição"
diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml
index e5d5abc6..bbaaaf3a 100644
--- a/web/translation/translate.ru_RU.toml
+++ b/web/translation/translate.ru_RU.toml
@@ -50,6 +50,7 @@
"fail" = "Ошибка"
"comment" = "Комментарий"
"success" = "Успешно"
+"lastOnline" = "Был(а) в сети"
"getVersion" = "Узнать версию"
"install" = "Установка"
"clients" = "Клиенты"
@@ -274,6 +275,7 @@
"trafficGetError" = "Ошибка получения данных о трафике"
"getNewX25519CertError" = "Ошибка при получении сертификата X25519."
"getNewmldsa65Error" = "Ошибка при получении сертификата mldsa65."
+"getNewVlessEncError" = "Ошибка при получении сертификата VlessEnc."
[pages.inbounds.stream.general]
"request" = "Запрос"
diff --git a/web/translation/translate.tr_TR.toml b/web/translation/translate.tr_TR.toml
index 2c0fdce2..286ea1c2 100644
--- a/web/translation/translate.tr_TR.toml
+++ b/web/translation/translate.tr_TR.toml
@@ -50,6 +50,7 @@
"fail" = "Başarısız"
"comment" = "Yorum"
"success" = "Başarılı"
+"lastOnline" = "Son çevrimiçi"
"getVersion" = "Sürümü Al"
"install" = "Yükle"
"clients" = "Müşteriler"
@@ -274,6 +275,7 @@
"trafficGetError" = "Trafik bilgisi alınırken hata oluştu"
"getNewX25519CertError" = "X25519 sertifikası alınırken hata oluştu."
"getNewmldsa65Error" = "mldsa65 sertifikası alınırken hata oluştu."
+"getNewVlessEncError" = "VlessEnc sertifikası alınırken hata oluştu."
[pages.inbounds.stream.general]
"request" = "İstek"
diff --git a/web/translation/translate.uk_UA.toml b/web/translation/translate.uk_UA.toml
index 6810f377..06634ef4 100644
--- a/web/translation/translate.uk_UA.toml
+++ b/web/translation/translate.uk_UA.toml
@@ -50,6 +50,7 @@
"fail" = "Помилка"
"comment" = "Коментар"
"success" = "Успішно"
+"lastOnline" = "Був(ла) онлайн"
"getVersion" = "Отримати версію"
"install" = "Встановити"
"clients" = "Клієнти"
@@ -274,6 +275,7 @@
"trafficGetError" = "Помилка отримання даних про трафік"
"getNewX25519CertError" = "Помилка при отриманні сертифіката X25519."
"getNewmldsa65Error" = "Помилка при отриманні сертифіката mldsa65."
+"getNewVlessEncError" = "Помилка при отриманні сертифіката VlessEnc."
[pages.inbounds.stream.general]
"request" = "Запит"
diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml
index 6a34f48d..b601b263 100644
--- a/web/translation/translate.vi_VN.toml
+++ b/web/translation/translate.vi_VN.toml
@@ -50,6 +50,7 @@
"fail" = "Thất bại"
"comment" = "Bình luận"
"success" = "Thành công"
+"lastOnline" = "Lần online gần nhất"
"getVersion" = "Lấy phiên bản"
"install" = "Cài đặt"
"clients" = "Các khách hàng"
@@ -273,7 +274,8 @@
"resetInboundClientTrafficSuccess" = "Đã đặt lại lưu lượng"
"trafficGetError" = "Lỗi khi lấy thông tin lưu lượng"
"getNewX25519CertError" = "Lỗi khi lấy chứng chỉ X25519."
-"getNewmldsa65Error" = "Lỗi khi lấy chúng tôi mldsa65."
+"getNewmldsa65Error" = "Lỗi khi lấy chứng chỉ mldsa65."
+"getNewVlessEncError" = "Lỗi khi lấy chứng chỉ VlessEnc."
[pages.inbounds.stream.general]
"request" = "Lời yêu cầu"
diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml
index 68d88efa..e0f2c222 100644
--- a/web/translation/translate.zh_CN.toml
+++ b/web/translation/translate.zh_CN.toml
@@ -50,6 +50,7 @@
"fail" = "失败"
"comment" = "评论"
"success" = "成功"
+"lastOnline" = "上次在线"
"getVersion" = "获取版本"
"install" = "安装"
"clients" = "客户端"
@@ -274,6 +275,7 @@
"trafficGetError" = "获取流量数据时出错"
"getNewX25519CertError" = "获取X25519证书时出错。"
"getNewmldsa65Error" = "获取mldsa65证书时出错。"
+"getNewVlessEncError" = "获取VlessEnc证书时出错。"
[pages.inbounds.stream.general]
"request" = "请求"
diff --git a/web/translation/translate.zh_TW.toml b/web/translation/translate.zh_TW.toml
index 429735c1..66b2bd33 100644
--- a/web/translation/translate.zh_TW.toml
+++ b/web/translation/translate.zh_TW.toml
@@ -50,6 +50,7 @@
"fail" = "失敗"
"comment" = "評論"
"success" = "成功"
+"lastOnline" = "上次上線"
"getVersion" = "獲取版本"
"install" = "安裝"
"clients" = "客戶端"
@@ -274,6 +275,7 @@
"trafficGetError" = "取得流量資料時發生錯誤"
"getNewX25519CertError" = "取得X25519憑證時發生錯誤。"
"getNewmldsa65Error" = "取得mldsa65憑證時發生錯誤。"
+"getNewVlessEncError" = "取得VlessEnc憑證時發生錯誤。"
[pages.inbounds.stream.general]
"request" = "請求"
diff --git a/x-ui.service b/x-ui.service
index 3b375c3e..e911ef56 100644
--- a/x-ui.service
+++ b/x-ui.service
@@ -10,13 +10,6 @@ WorkingDirectory=/usr/local/x-ui/
ExecStart=/usr/local/x-ui/x-ui
Restart=on-failure
RestartSec=5s
-ProtectHome=tmpfs
-ProtectKernelModules=true
-ProtectControlGroups=true
-ProtectKernelLogs=true
-ProtectHostname=true
-ProtectClock=true
-MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.target
diff --git a/xray/client_traffic.go b/xray/client_traffic.go
index 883de2cc..fe527d55 100644
--- a/xray/client_traffic.go
+++ b/xray/client_traffic.go
@@ -11,4 +11,5 @@ type ClientTraffic struct {
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
Total int64 `json:"total" form:"total"`
Reset int `json:"reset" form:"reset" gorm:"default:0"`
+ LastOnline int64 `json:"lastOnline" form:"lastOnline" gorm:"default:0"`
}
|