精简: 去掉 Telegram 机器人+通知: tgbot 包/stats-notify 与 hash 清理 job/登录通知/backuptotgbot/testTgBot/全部 tg* 设置/locale Bot 本地化/SecretClears 机制; 连带清理 Swagger/外部流量/邮件/2FA 的残留测试

This commit is contained in:
Muse
2026-10-20 10:11:35 +00:00
parent 1498d58f14
commit e42b5d770d
37 changed files with 32 additions and 5471 deletions
@@ -4,10 +4,7 @@ import (
"path/filepath"
"testing"
"github.com/xlzd/gotp"
"github.com/mhsanaei/3x-ui/v3/internal/database"
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
)
func setupSettingTestDB(t *testing.T) {
@@ -22,126 +19,6 @@ func setupSettingTestDB(t *testing.T) {
})
}
func TestGetAllSettingViewRedactsSecrets(t *testing.T) {
setupSettingTestDB(t)
s := &SettingService{}
if err := s.saveSetting("tgBotToken", "telegram-secret"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("twoFactorToken", "totp-secret"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("ldapPassword", "ldap-secret"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("smtpPassword", "smtp-secret"); err != nil {
t.Fatal(err)
}
if err := database.GetDB().Create(&model.ApiToken{Name: "test", Token: "api-secret", Enabled: true}).Error; err != nil {
t.Fatal(err)
}
view, err := s.GetAllSettingView()
if err != nil {
t.Fatal(err)
}
if view.TgBotToken != "" || view.TwoFactorToken != "" || view.LdapPassword != "" || view.SmtpPassword != "" {
t.Fatalf("settings view leaked secrets: %#v", view)
}
if !view.HasTgBotToken || !view.HasTwoFactorToken || !view.HasLdapPassword || !view.HasApiToken || !view.HasSmtpPassword {
t.Fatalf("settings view did not report configured secret flags: %#v", view)
}
}
func TestUpdateAllSettingPreservesRedactedSecrets(t *testing.T) {
setupSettingTestDB(t)
s := &SettingService{}
if err := s.saveSetting("tgBotToken", "telegram-secret"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("ldapPassword", "ldap-secret"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("twoFactorEnable", "true"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("twoFactorToken", "totp-secret"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("smtpPassword", "smtp-secret"); err != nil {
t.Fatal(err)
}
view, err := s.GetAllSettingView()
if err != nil {
t.Fatal(err)
}
settings := &view.AllSetting
if err := s.UpdateAllSetting(settings, SecretClears{}); err != nil {
t.Fatal(err)
}
if got, _ := s.GetTgBotToken(); got != "telegram-secret" {
t.Fatalf("tg token = %q, want preserved secret", got)
}
if got, _ := s.GetLdapPassword(); got != "ldap-secret" {
t.Fatalf("ldap password = %q, want preserved secret", got)
}
if got, _ := s.GetTwoFactorToken(); got != "totp-secret" {
t.Fatalf("2fa token = %q, want preserved secret", got)
}
if got, _ := s.GetSmtpPassword(); got != "smtp-secret" {
t.Fatalf("smtp password = %q, want preserved secret", got)
}
}
func TestUpdateAllSettingClearsFlaggedSecrets(t *testing.T) {
setupSettingTestDB(t)
s := &SettingService{}
if err := s.saveSetting("tgBotToken", "telegram-secret"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("ldapPassword", "ldap-secret"); err != nil {
t.Fatal(err)
}
if err := s.saveSetting("smtpPassword", "smtp-secret"); err != nil {
t.Fatal(err)
}
view, err := s.GetAllSettingView()
if err != nil {
t.Fatal(err)
}
if err := s.UpdateAllSetting(&view.AllSetting, SecretClears{SmtpPassword: true}); err != nil {
t.Fatal(err)
}
if got, _ := s.GetSmtpPassword(); got != "" {
t.Fatalf("smtp password = %q, want cleared", got)
}
if got, _ := s.GetTgBotToken(); got != "telegram-secret" {
t.Fatalf("tg token = %q, unflagged secret must stay preserved", got)
}
if got, _ := s.GetLdapPassword(); got != "ldap-secret" {
t.Fatalf("ldap password = %q, unflagged secret must stay preserved", got)
}
view, err = s.GetAllSettingView()
if err != nil {
t.Fatal(err)
}
if view.HasSmtpPassword {
t.Fatal("hasSmtpPassword must report false after clearing")
}
if err := s.UpdateAllSetting(&view.AllSetting, SecretClears{TgBotToken: true, LdapPassword: true}); err != nil {
t.Fatal(err)
}
if got, _ := s.GetTgBotToken(); got != "" {
t.Fatalf("tg token = %q, want cleared", got)
}
if got, _ := s.GetLdapPassword(); got != "" {
t.Fatalf("ldap password = %q, want cleared", got)
}
}
func TestSanitizePublicHTTPURLBlocksPrivateAddressUnlessAllowed(t *testing.T) {
if _, err := SanitizePublicHTTPURL("http://127.0.0.1:8080/hook", false); err == nil {
t.Fatal("expected localhost URL to be blocked")
@@ -151,25 +28,6 @@ func TestSanitizePublicHTTPURLBlocksPrivateAddressUnlessAllowed(t *testing.T) {
}
}
func TestVerifyTwoFactorCode(t *testing.T) {
setupSettingTestDB(t)
s := &SettingService{}
if err := s.saveSetting("twoFactorEnable", "true"); err != nil {
t.Fatal(err)
}
const token = "JBSWY3DPEHPK3PXP"
if err := s.saveSetting("twoFactorToken", token); err != nil {
t.Fatal(err)
}
if err := s.VerifyTwoFactorCode(gotp.NewDefaultTOTP(token).Now()); err != nil {
t.Fatalf("valid code rejected: %v", err)
}
if err := s.VerifyTwoFactorCode("000000"); err == nil {
t.Fatal("invalid code accepted")
}
}
func TestGetSecret_FallbacksOnEmptyDatabaseSetting(t *testing.T) {
setupSettingTestDB(t)
s := &SettingService{}