任务执行1-19

This commit is contained in:
zxr
2026-06-26 12:51:50 +08:00
parent 175d9f8f94
commit 19908230f2
19 changed files with 2615 additions and 1260 deletions

View File

@@ -0,0 +1,207 @@
package audit
import (
"errors"
"fmt"
"strconv"
"strings"
"time"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/ops/logs/internal/impl"
"git.apinb.com/ops/logs/internal/models"
"github.com/gin-gonic/gin"
)
func ListAuditLogs(ctx *gin.Context) {
page, size := pageAndSize(ctx.DefaultQuery("page", "1"), ctx.DefaultQuery("page_size", "50"))
q := impl.DBService.Model(&models.AuditLog{})
if v := strings.TrimSpace(ctx.Query("source_service")); v != "" {
q = q.Where("source_service = ?", v)
}
if v := strings.TrimSpace(ctx.Query("actor_id")); v != "" {
q = q.Where("actor_id = ?", v)
}
if v := strings.TrimSpace(ctx.Query("action")); v != "" {
q = q.Where("action = ?", v)
}
if v := strings.TrimSpace(ctx.Query("object_type")); v != "" {
q = q.Where("object_type = ?", v)
}
if v := strings.TrimSpace(ctx.Query("object_id")); v != "" {
q = q.Where("object_id = ?", v)
}
if v := strings.TrimSpace(ctx.Query("operation_risk")); v != "" {
q = q.Where("operation_risk = ?", v)
}
if v := strings.TrimSpace(ctx.Query("result")); v != "" {
q = q.Where("result = ?", v)
}
var total int64
_ = q.Count(&total).Error
var rows []models.AuditLog
if err := q.Order("id desc").Offset((page - 1) * size).Limit(size).Find(&rows).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
infra.Response.Success(ctx, gin.H{"total": total, "page": page, "page_size": size, "items": rows})
}
func CreateAuditLog(ctx *gin.Context) {
var req Record
if err := ctx.ShouldBindJSON(&req); err != nil {
infra.Response.Error(ctx, err)
return
}
req.ClientIP = firstNonEmpty(req.ClientIP, ctx.ClientIP())
req.RequestMethod = firstNonEmpty(req.RequestMethod, ctx.Request.Method)
req.RequestPath = firstNonEmpty(req.RequestPath, ctx.FullPath())
row, err := SaveRecord(req)
if err != nil {
infra.Response.Error(ctx, err)
return
}
infra.Response.Success(ctx, row)
}
func ListApprovals(ctx *gin.Context) {
page, size := pageAndSize(ctx.DefaultQuery("page", "1"), ctx.DefaultQuery("page_size", "50"))
q := impl.DBService.Model(&models.DangerousOperationApproval{})
if v := strings.TrimSpace(ctx.Query("source_service")); v != "" {
q = q.Where("source_service = ?", v)
}
if v := strings.TrimSpace(ctx.Query("status")); v != "" {
q = q.Where("status = ?", v)
}
if v := strings.TrimSpace(ctx.Query("requester_id")); v != "" {
q = q.Where("requester_id = ?", v)
}
if v := strings.TrimSpace(ctx.Query("object_type")); v != "" {
q = q.Where("object_type = ?", v)
}
var total int64
_ = q.Count(&total).Error
var rows []models.DangerousOperationApproval
if err := q.Order("id desc").Offset((page - 1) * size).Limit(size).Find(&rows).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
infra.Response.Success(ctx, gin.H{"total": total, "page": page, "page_size": size, "items": rows})
}
func CreateApproval(ctx *gin.Context) {
var req ApprovalRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
infra.Response.Error(ctx, err)
return
}
req = NormalizeApproval(req)
if req.RequestID == "" {
req.RequestID = fmt.Sprintf("apr-%d", time.Now().UnixNano())
}
if err := ValidateApprovalRequest(req); err != nil {
infra.Response.Error(ctx, err)
return
}
row := models.DangerousOperationApproval{
RequestID: req.RequestID,
SourceService: req.SourceService,
Action: req.Action,
ObjectType: req.ObjectType,
ObjectID: req.ObjectID,
RequesterID: req.RequesterID,
RequesterName: req.RequesterName,
Reason: req.Reason,
BeforeJSON: req.BeforeJSON,
AfterJSON: req.AfterJSON,
Status: ApprovalPending,
}
if err := impl.DBService.Create(&row).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
infra.Response.Success(ctx, row)
}
func ApproveApproval(ctx *gin.Context) {
reviewApproval(ctx, ApprovalApproved)
}
func RejectApproval(ctx *gin.Context) {
reviewApproval(ctx, ApprovalRejected)
}
func reviewApproval(ctx *gin.Context, next string) {
id, err := parseUintParam(ctx, "id")
if err != nil {
infra.Response.Error(ctx, err)
return
}
var body struct {
ReviewerID string `json:"reviewer_id"`
ReviewerName string `json:"reviewer_name"`
ReviewComment string `json:"review_comment"`
}
if err := ctx.ShouldBindJSON(&body); err != nil {
infra.Response.Error(ctx, err)
return
}
var row models.DangerousOperationApproval
if err := impl.DBService.First(&row, id).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
req := ApprovalRequest{
RequestID: row.RequestID,
SourceService: row.SourceService,
Action: row.Action,
ObjectType: row.ObjectType,
ObjectID: row.ObjectID,
RequesterID: row.RequesterID,
Status: row.Status,
}
nextReq, err := Transition(req, next, body.ReviewerID, body.ReviewComment)
if err != nil {
infra.Response.Error(ctx, err)
return
}
row.Status = nextReq.Status
row.ReviewerID = nextReq.ReviewerID
row.ReviewerName = strings.TrimSpace(body.ReviewerName)
row.ReviewComment = nextReq.ReviewComment
row.ReviewedAt = nextReq.ReviewedAt
if err := impl.DBService.Save(&row).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
infra.Response.Success(ctx, row)
}
func parseUintParam(ctx *gin.Context, name string) (uint, error) {
v, err := strconv.ParseUint(ctx.Param(name), 10, 32)
if err != nil || v == 0 {
return 0, errors.New("invalid id")
}
return uint(v), nil
}
func pageAndSize(pageText, sizeText string) (int, int) {
page, _ := strconv.Atoi(pageText)
size, _ := strconv.Atoi(sizeText)
if page < 1 {
page = 1
}
if size < 1 || size > 500 {
size = 50
}
return page, size
}
func firstNonEmpty(values ...string) string {
for _, value := range values {
if strings.TrimSpace(value) != "" {
return strings.TrimSpace(value)
}
}
return ""
}