mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-07-12 16:02:18 +08:00
修复: 后端审查发现的 5 项问题
根据 Spec + Code Quality 双审查修复: 1. BatchCreate 事务保护(node_service.go/node_repository.go) 原循环 Create 在 DB 约束失败时会残留半截数据。改为预先构造所有 Node 再走 repo.BatchCreate 单一事务,任一失败整体回滚。 2. Peek 语义与 Consume 对齐(agent_install_token_repository.go) FindByToken 无条件返回任意记录,导致已消费/已过期的僵尸 token 可通过 compose 端点的 mode 检查但必然 Consume 失败,出现 410 假错。 新增 FindValidByToken,Peek 改用之。 3. MasterURL / AgentToken / AgentVersion 渲染前校验(installscript/renderer.go) 防止 YAML 注入(换行/引号逃逸 compose 配置)、shell 注入($(...))、 非法字符。加 TestRenderScriptRejects* 系列测试覆盖。 4. ipLimiter 无界增长修复(install_handler.go) 新增 gc 方法 + startGC 后台协程,每 window 周期清理过期 IP 条目。 RouterDependencies.Context 控制生命周期;app 传入 ctx,测试 t.Cleanup 取消。 5. CreateInstallToken 的 CreatedByID 从 JWT subject 解析(node_handler.go) 原硬编码 0 导致审计不可追溯。新增 resolveCurrentUserID helper, 借助 UserRepository 把 JWT subject(用户名)→ user.ID;失败退回 0。
This commit is contained in:
@@ -402,23 +402,29 @@ func (s *NodeService) BatchCreate(ctx context.Context, names []string) ([]NodeCr
|
||||
}
|
||||
}
|
||||
|
||||
results := make([]NodeCreateResult, 0, len(cleaned))
|
||||
// 预先构造所有 Node,token 生成在事务外完成(纯内存操作,失败不会影响 DB 状态)
|
||||
nodes := make([]*model.Node, 0, len(cleaned))
|
||||
now := time.Now().UTC()
|
||||
for _, name := range cleaned {
|
||||
tok, err := generateToken()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate token: %w", err)
|
||||
}
|
||||
node := &model.Node{
|
||||
nodes = append(nodes, &model.Node{
|
||||
Name: name,
|
||||
Token: tok,
|
||||
Status: model.NodeStatusOffline,
|
||||
IsLocal: false,
|
||||
LastSeen: time.Now().UTC(),
|
||||
}
|
||||
if err := s.repo.Create(ctx, node); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results = append(results, NodeCreateResult{ID: node.ID, Name: node.Name})
|
||||
LastSeen: now,
|
||||
})
|
||||
}
|
||||
// 事务内批量创建:任一失败整体回滚
|
||||
if err := s.repo.BatchCreate(ctx, nodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results := make([]NodeCreateResult, 0, len(nodes))
|
||||
for _, n := range nodes {
|
||||
results = append(results, NodeCreateResult{ID: n.ID, Name: n.Name})
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user