fix(ctxmgr): EnsureChatSession 归属 COALESCE 改为已有值优先(R-1c)
防止跨用户通过 upsert/消息落库覆盖已绑定的 chat_sessions.user_id;新增 EnsureChatSessionOwned。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -32,7 +32,7 @@ func (m *ContextManager) EnsureChatSession(ctx context.Context, sessionID string
|
||||
VALUES ($1, $2, $3, $4, now(), now())
|
||||
ON CONFLICT (session_id) DO UPDATE SET
|
||||
title = COALESCE(NULLIF($4, ''), chat_sessions.title),
|
||||
user_id = COALESCE($2, chat_sessions.user_id),
|
||||
user_id = COALESCE(chat_sessions.user_id, $2),
|
||||
project_id = COALESCE($3, chat_sessions.project_id),
|
||||
updated_at = now()
|
||||
`, sessionID, uid, pid, title)
|
||||
@@ -79,7 +79,7 @@ func (m *ContextManager) EnsureChatSession(ctx context.Context, sessionID string
|
||||
if title != "" {
|
||||
sess.Title = title
|
||||
}
|
||||
if userID > 0 {
|
||||
if userID > 0 && sess.UserID <= 0 {
|
||||
sess.UserID = userID
|
||||
}
|
||||
if projectID > 0 {
|
||||
@@ -97,6 +97,22 @@ func (m *ContextManager) EnsureChatSession(ctx context.Context, sessionID string
|
||||
return ©, nil
|
||||
}
|
||||
|
||||
// ErrSessionOwnerMismatch 表示调用者试图操作已绑定给其他用户的会话。
|
||||
var ErrSessionOwnerMismatch = errors.New("ctxmgr: session owner mismatch")
|
||||
|
||||
// EnsureChatSessionOwned 在写入前校验归属:已绑定且不匹配调用者时返回
|
||||
// ErrSessionOwnerMismatch;未绑定或本就是调用者本人时正常落地。
|
||||
func (m *ContextManager) EnsureChatSessionOwned(
|
||||
ctx context.Context, sessionID string, callerUserID, projectID int64, title string,
|
||||
) (*ChatSessionSummary, error) {
|
||||
if callerUserID > 0 {
|
||||
if owner, err := m.GetSessionOwnerID(ctx, sessionID); err == nil && owner > 0 && owner != callerUserID {
|
||||
return nil, ErrSessionOwnerMismatch
|
||||
}
|
||||
}
|
||||
return m.EnsureChatSession(ctx, sessionID, callerUserID, projectID, title)
|
||||
}
|
||||
|
||||
// ListChatSessions 分页查询历史会话列表
|
||||
func (m *ContextManager) ListChatSessions(ctx context.Context, filter SessionFilter) ([]ChatSessionSummary, error) {
|
||||
if filter.Limit <= 0 {
|
||||
|
||||
@@ -190,13 +190,13 @@ func (m *ContextManager) RecordUserMessageWithID(ctx context.Context, sessionID
|
||||
}
|
||||
}
|
||||
|
||||
// 确保会话存在
|
||||
// 确保会话存在(user_id 已有值优先,防止跨用户覆盖归属)
|
||||
_, _ = m.pool.Exec(ctx, `
|
||||
INSERT INTO chat_sessions (session_id, user_id, project_id, title, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, '对话协同会话', now(), now())
|
||||
ON CONFLICT (session_id) DO UPDATE SET
|
||||
updated_at = now(),
|
||||
user_id = COALESCE($2, chat_sessions.user_id),
|
||||
user_id = COALESCE(chat_sessions.user_id, $2),
|
||||
project_id = COALESCE($3, chat_sessions.project_id)
|
||||
`, sessionID, uid, pid)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user