mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-02 11:15:03 +03:00
fix(clients): store client group names trimmed
The groups page lists clients.group_name as stored, while every group action trims the name it is given. A name with surrounding white space, saved by a node snapshot or by a client edit, was listed as a separate group, and deleting, renaming or resetting that row acted on the real group of the trimmed name instead. Group names are trimmed wherever a client record is built or updated, and a one-time seeder folds stored names onto their trimmed form.
This commit is contained in:
+27
-1
@@ -1530,7 +1530,7 @@ func runSeeders(isUsersEmpty bool) error {
|
||||
}
|
||||
|
||||
if empty && isUsersEmpty {
|
||||
seeders := []string{"UserPasswordHash", "ClientsTable", "InboundClientsArrayFix", "InboundClientTgIdFix2", "InboundClientSubIdFix", "FreedomFinalRulesReverseFix", "FreedomFinalRulesPrivateEgressBlock", "UppercaseFreedomFinalRulesFix", "InboundRealityFinalmaskTcpStrip", "ApiTokensHash", "LegacyProxySettingsCleanup", "SessionSecretRotation", "OutboundRemovedKeysFix", "FreedomDomainStrategyFix", "DNSOutboundLegacyKeysFix", "DNSOutboundQTypeZeroFix", "WireguardDomainStrategyFix", "XdnsFinalmaskNamesAddrsFix", "UDPHopClientMaskFix", "HostVerifyPeerCertByNameBoolFix", "HostMihomoX25519Reset", "WireguardPeersToClients", "MtprotoSecretsToClients", "NodeInboundsAdopted", "NodeDownNotified", "ResetIpLimitNoFail2ban"}
|
||||
seeders := []string{"UserPasswordHash", "ClientsTable", "InboundClientsArrayFix", "InboundClientTgIdFix2", "InboundClientSubIdFix", "FreedomFinalRulesReverseFix", "FreedomFinalRulesPrivateEgressBlock", "UppercaseFreedomFinalRulesFix", "InboundRealityFinalmaskTcpStrip", "ApiTokensHash", "LegacyProxySettingsCleanup", "SessionSecretRotation", "OutboundRemovedKeysFix", "FreedomDomainStrategyFix", "DNSOutboundLegacyKeysFix", "DNSOutboundQTypeZeroFix", "WireguardDomainStrategyFix", "XdnsFinalmaskNamesAddrsFix", "UDPHopClientMaskFix", "HostVerifyPeerCertByNameBoolFix", "HostMihomoX25519Reset", "WireguardPeersToClients", "MtprotoSecretsToClients", "NodeInboundsAdopted", "NodeDownNotified", "ResetIpLimitNoFail2ban", "ClientGroupNameTrim"}
|
||||
for _, name := range seeders {
|
||||
if err := db.Create(&model.HistoryOfSeeders{SeederName: name}).Error; err != nil {
|
||||
return err
|
||||
@@ -1713,6 +1713,12 @@ func runSeeders(isUsersEmpty bool) error {
|
||||
}
|
||||
}
|
||||
|
||||
if !slices.Contains(seedersHistory, "ClientGroupNameTrim") {
|
||||
if err := trimClientGroupNames(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := seedHostsFromExternalProxy(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1908,6 +1914,26 @@ func clearLegacyProxySettings() error {
|
||||
})
|
||||
}
|
||||
|
||||
// The groups page addresses a group by its trimmed name, so a padded stored name listed as
|
||||
// its own group while every action on it hit the trimmed one.
|
||||
func trimClientGroupNames() error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
var names []string
|
||||
if err := tx.Model(&model.ClientRecord{}).Distinct().Pluck("group_name", &names).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for _, name := range names {
|
||||
if trimmed := strings.TrimSpace(name); trimmed != name {
|
||||
if err := tx.Model(&model.ClientRecord{}).Where("group_name = ?", name).
|
||||
UpdateColumn("group_name", trimmed).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return tx.Create(&model.HistoryOfSeeders{SeederName: "ClientGroupNameTrim"}).Error
|
||||
})
|
||||
}
|
||||
|
||||
// Secrets stored before v2.8.3 came from math/rand (a 31-bit clock seed up to v2.1.3);
|
||||
// GetSecret draws a crypto/rand one on the next start.
|
||||
func dropPreUpgradeSessionSecret() error {
|
||||
|
||||
Reference in New Issue
Block a user