fix: Z35 禁止用中文昵称作 Postgres 库名,发布时纠正脏数据

绑定 database_name 改为 user_{id};publish 遇非法库名 Sanitize 并回写,避免 EnsureDatabase 400。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
whm
2026-08-07 01:41:20 +08:00
parent d489169bec
commit a80559d353
4 changed files with 65 additions and 10 deletions

View File

@@ -7,9 +7,10 @@ import (
"strings"
"time"
"aijianzhan/platform/internal/agentcap"
"aijianzhan/platform/internal/agentstore"
"aijianzhan/platform/internal/audit"
"aijianzhan/platform/internal/authx"
"aijianzhan/platform/internal/agentcap"
"aijianzhan/platform/internal/blueprint"
"aijianzhan/platform/internal/meta"
"aijianzhan/platform/internal/schema"
@@ -264,16 +265,26 @@ func (l *PublishLogic) Publish(slug string, req *types.PublishReq) (*types.Publi
schemaName := bp.AssignSchemaName(tenantID)
dbName := bp.AssignDatabaseName(tenantID)
// Z8c智能体若绑定了 database_name新建模块优先落到该库database_per_app
// Z8c智能体若绑定了合法 database_name新建模块优先落到该库database_per_app
// Z35中文昵称等非法名不得用于 EnsureDatabase回落 AssignDatabaseName
if authx.Role(l.ctx) == authx.RoleAgent && l.svcCtx.Agents != nil {
if aid := authx.AgentID(l.ctx); aid > 0 {
if acc, err := l.svcCtx.Agents.Get(l.ctx, tenantID, aid); err == nil && acc != nil {
if dn := strings.TrimSpace(acc.DatabaseName); dn != "" {
if dn := strings.TrimSpace(acc.DatabaseName); dn != "" && schema.ValidDBName(dn) {
if !exists || existing.DatabaseName == "" {
bp.Storage.Mode = "database_per_app"
schemaName = bp.AssignSchemaName(tenantID)
dbName = dn
}
} else if dn != "" && !schema.ValidDBName(dn) {
// 历史脏数据(如 DisplayName 当库名):纠正智能体落点库名,避免反复 400
safeName := schema.SanitizeDBName(tenantID, slug)
_, _ = l.svcCtx.Agents.Update(l.ctx, tenantID, aid, agentstore.UpdateInput{
DatabaseName: &safeName,
})
bp.Storage.Mode = "database_per_app"
schemaName = bp.AssignSchemaName(tenantID)
dbName = safeName
}
}
}
@@ -294,7 +305,7 @@ func (l *PublishLogic) Publish(slug string, req *types.PublishReq) (*types.Publi
schemaName = existing.SchemaName
bp.Storage.SchemaName = existing.SchemaName
}
if existing.DatabaseName != "" {
if existing.DatabaseName != "" && schema.ValidDBName(existing.DatabaseName) {
dbName = existing.DatabaseName
}
ddl, err = schema.BuildPostgresDDL(bp)

View File

@@ -191,10 +191,12 @@ func (l *AuthLogic) bindUserHostSync(u *userstore.User, hostKey, name, localID,
return nil, "", fmt.Errorf("host_key 已绑定其它公司")
}
online := fmt.Sprintf("%s_u%d", dbsync.ResolveOnlineDBID("", ch.ID), u.UserID)
dbName := strings.TrimSpace(u.DisplayName)
if dbName == "" {
dbName = fmt.Sprintf("user_%d", u.UserID)
// DisplayName 可中文Postgres 物理库名必须 [a-z][a-z0-9_]{1,47}Z35
display := strings.TrimSpace(u.DisplayName)
if display == "" {
display = fmt.Sprintf("user_%d", u.UserID)
}
dbName := fmt.Sprintf("user_%d", u.UserID)
updated, err := l.svcCtx.Agents.AttachSyncBind(l.ctx, acc.AgentID, u.TenantID, ch.ID, online, dbName, true)
if err != nil {
return nil, "", err
@@ -214,7 +216,7 @@ func (l *AuthLogic) bindUserHostSync(u *userstore.User, hostKey, name, localID,
OnlineDBID: online,
ChannelID: ch.ID,
DatabaseName: dbName,
DisplayName: dbName,
DisplayName: display,
Note: note,
})
return updated, secret, nil

View File

@@ -90,3 +90,21 @@ func SanitizeDBName(tenantID int64, slug string) string {
}
return name
}
// ValidDBName 是否可作为 Postgres 物理库名CREATE DATABASE
func ValidDBName(dbName string) bool {
return dbNameRe.MatchString(strings.TrimSpace(dbName))
}
// SafePhysicalDBName 优先用 preferred非法则用 fallback仍非法则 user_fallback。
func SafePhysicalDBName(preferred, fallback string) string {
p := strings.TrimSpace(preferred)
if ValidDBName(p) {
return p
}
f := strings.TrimSpace(fallback)
if ValidDBName(f) {
return f
}
return "appdb_default"
}