Scert/backend/internal/repository/project_member_failures.go

47 lines
1.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"context"
"errors"
"fmt"
"time"
)
// ProjectMemberFailure 的操作者必须来自已验证会话快照;未登录时留空,不能从请求体读取。
type ProjectMemberFailure struct {
ActorID string
ProjectID string
UserID string
Action string
StatusCode int
RequestID string
}
// 失败事件独立于已回滚的变更事务,范围由实际项目解析,不将不存在的项目伪装为系统范围。
func (r *SQLProjectMemberRepository) RecordProjectMemberFailure(ctx context.Context, failure ProjectMemberFailure) error {
if err := r.ensureDB(); err != nil {
return err
}
if failure.Action != "project_member.list" && failure.Action != "project_member.grant" && failure.Action != "project_member.revoke" {
return errors.New("项目成员失败审计动作无效")
}
if failure.StatusCode < 400 || failure.StatusCode > 599 || len(failure.ActorID) > 128 || len(failure.UserID) > 128 || len(failure.ProjectID) > 128 || len(failure.RequestID) > 128 {
return errors.New("项目成员失败审计参数无效")
}
message := fmt.Sprintf("请求被拒绝或执行失败:HTTP %d;请求编号:%s", failure.StatusCode, failure.RequestID)
result, err := r.db.ExecContext(ctx, Rebind(r.driver, `INSERT INTO audit_logs
(action, resource_type, resource_id, status, message, created_at, scope_type, project_id, task_id, operator_id)
SELECT ?, 'project_member', ?, 'failed', ?, ?,
CASE WHEN p.id IS NULL THEN 'unknown' ELSE 'project' END, COALESCE(p.id, ''), '', ?
FROM (SELECT 1 AS marker) audit_event LEFT JOIN projects p ON p.id = ?`),
failure.Action, failure.UserID, message, time.Now().UTC(), failure.ActorID, failure.ProjectID)
if err != nil {
return fmt.Errorf("保存项目成员失败审计失败:%w", err)
}
count, err := result.RowsAffected()
if err != nil || count != 1 {
return errors.New("项目成员失败审计未完整写入")
}
return nil
}