feat: 迁移预警处理审核与备注附件流程
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/glebarez/sqlite"
|
||||
"gorm.io/gorm"
|
||||
businessbiz "kra/internal/biz/business"
|
||||
"kra/internal/biz/system"
|
||||
businessdata "kra/internal/data/business"
|
||||
systemdata "kra/internal/data/system"
|
||||
"kra/internal/server/handler"
|
||||
"kra/internal/server/router"
|
||||
businessservice "kra/internal/service/business"
|
||||
)
|
||||
|
||||
func TestAlertRecordHTTPCompleteWorkflowAndVisibility(t *testing.T) {
|
||||
db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "records.db")), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pool, _ := db.DB()
|
||||
t.Cleanup(func() { _ = pool.Close() })
|
||||
for _, step := range append(systemdata.Migrations(), businessdata.Migrations()...) {
|
||||
if err := step.Migrate(db); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, sql := range []string{
|
||||
"INSERT INTO sys_users(id,uuid,username,level,parent_id,id_path,enable) VALUES(1,'root','admin',0,0,'0',1),(7,'owner','owner',1,0,'0',1),(8,'child','child',2,7,'0,7',1),(9,'leaf','leaf',3,8,'0,7,8',1),(10,'sibling','sibling',2,7,'0,7',1),(99,'other','other',1,0,'0',1)",
|
||||
"CREATE TABLE tab_promote(id INTEGER,source_db TEXT,busier_id INTEGER,promote_level INTEGER,status INTEGER)",
|
||||
"INSERT INTO tab_promote VALUES(100,'lx',14,1,0),(100,'hw',14,1,1),(100,'yq',14,1,1)",
|
||||
"INSERT INTO sys_user_bind_platform(user_id,source_db,platform_busier_id,status) VALUES(9,'lx',14,'0'),(10,'hw',14,'0'),(99,'yq',14,'0')",
|
||||
"INSERT INTO sys_alert_record(id,platform_code,target_promote_id,business_id,rule_name,status,created_at,updated_at) VALUES(9007199254740993,'lx',100,7,'目标规则',1,'2026-11-03 08:00:00','2026-11-03 08:00:00'),(2,'hw',100,7,'平级规则',1,'2026-11-03 08:00:00','2026-11-03 08:00:00'),(3,'lx',100,99,'归属错误',1,'2026-11-03 08:00:00','2026-11-03 08:00:00'),(4,'yq',100,99,'其他规则',1,'2026-11-03 08:00:00','2026-11-03 08:00:00'),(5,'lx',100,7,'关闭规则',5,'2026-11-03 08:00:00','2026-11-03 08:00:00'),(6,'lx',100,7,'待审规则',3,'2026-11-03 08:00:00','2026-11-03 08:00:00')",
|
||||
"INSERT INTO media_file_upload_and_downloads(id,url) VALUES(1,'/files/one.png'),(2,'/files/two.png')",
|
||||
} {
|
||||
if err := db.Exec(sql).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
provider := businessHTTPData{db}
|
||||
accounts := businessbiz.NewAccountUsecase(businessdata.NewAccountRepo(provider))
|
||||
service := businessservice.NewAlertRecordService(businessbiz.NewAlertRecordUsecase(businessdata.NewAlertRecordRepo(provider), accounts))
|
||||
engine := gin.New()
|
||||
engine.Use(func(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.GetHeader("X-Test-User"), 10, 64)
|
||||
authority := uint(901)
|
||||
if id == 1 {
|
||||
authority = 888
|
||||
}
|
||||
c.Request = c.Request.WithContext(system.NewActorContext(c.Request.Context(), system.Actor{UserID: uint(id), AuthorityID: authority}))
|
||||
c.Next()
|
||||
})
|
||||
router.RegisterAlertRecord(engine.Group(""), handler.NewAlertRecord(service))
|
||||
server := httptest.NewServer(engine)
|
||||
defer server.Close()
|
||||
call := func(user int, method, path, body string, expected int) map[string]any {
|
||||
t.Helper()
|
||||
req, err := http.NewRequest(method, server.URL+path, strings.NewReader(body))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Test-User", strconv.Itoa(user))
|
||||
response, err := server.Client().Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
var result map[string]any
|
||||
if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result["code"] != float64(expected) {
|
||||
t.Fatalf("%s %s 用户%d 响应错误: %+v", method, path, user, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
list := func(user int, query string, total int) map[string]any {
|
||||
t.Helper()
|
||||
data := call(user, "GET", "/sw/alertRecord/list"+query, "", 0)["data"].(map[string]any)
|
||||
if data["pageData"].(map[string]any)["total"] != float64(total) {
|
||||
t.Fatalf("列表范围错误: %+v", data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
list(1, "", 6)
|
||||
list(7, "", 4)
|
||||
list(8, "", 3)
|
||||
list(9, "", 3)
|
||||
list(7, "?businessId=8", 3)
|
||||
list(8, "?businessId=99", 0)
|
||||
list(1, "?businessId=8", 4)
|
||||
list(8, "?platformCodes=hw", 0)
|
||||
data := list(8, "?status=1&ruleName=%E7%9B%AE%E6%A0%87", 1)
|
||||
if len(data["statusCount"].(map[string]any)) != 3 {
|
||||
t.Fatal("汇总错误继承列表筛选")
|
||||
}
|
||||
const id = "9007199254740993"
|
||||
detailPath := "/sw/alertRecord/detail/" + id
|
||||
data = call(9, "GET", detailPath, "", 0)["data"].(map[string]any)
|
||||
if data["canAudit"] != false || data["alertRecord"].(map[string]any)["id"] != id {
|
||||
t.Fatal("详情审核权限或大 ID 精度错误")
|
||||
}
|
||||
call(8, "GET", "/sw/alertRecord/detail/2", "", 7)
|
||||
call(8, "GET", "/sw/alertRecord/detail/3", "", 7)
|
||||
call(99, "GET", detailPath, "", 7)
|
||||
body := `{"alertId":"` + id + `"}`
|
||||
process := func(user int, action, note string, code int) {
|
||||
payload := body
|
||||
if note != "" {
|
||||
encoded, _ := json.Marshal(note)
|
||||
payload = fmt.Sprintf(`{"alertId":"%s","note":%s}`, id, encoded)
|
||||
}
|
||||
call(user, "POST", "/sw/alertRecord/"+action, payload, code)
|
||||
}
|
||||
process(9, "submitAudit", "", 7)
|
||||
process(9, "startProcess", "开始排查", 0)
|
||||
process(9, "startProcess", "重复开始", 7)
|
||||
process(9, "submitAudit", "", 0)
|
||||
process(1, "approve", "超管不能绕过等级", 7)
|
||||
process(8, "approve", "", 7)
|
||||
process(9, "approve", "", 7)
|
||||
process(7, "reject", "补充说明", 0)
|
||||
process(9, "reProcess", "", 0)
|
||||
process(9, "submitAudit", "", 0)
|
||||
process(7, "approve", "", 0)
|
||||
process(9, "reProcess", "", 7)
|
||||
data = call(7, "GET", detailPath, "", 0)["data"].(map[string]any)
|
||||
if data["canAudit"] != true || data["alertRecord"].(map[string]any)["status"] != float64(5) || len(data["operationLogs"].([]any)) != 8 {
|
||||
t.Fatalf("完整处理审核日志错误: %+v", data)
|
||||
}
|
||||
call(9, "POST", "/sw/alertRecord/addNote", `{"alertId":"`+id+`","noteContent":" ","attachmentIds":[1]}`, 7)
|
||||
call(9, "POST", "/sw/alertRecord/addNote", `{"alertId":"`+id+`","noteContent":"关闭后补充","attachmentIds":[2,"1"]}`, 0)
|
||||
data = call(9, "GET", detailPath, "", 0)["data"].(map[string]any)
|
||||
logs := data["operationLogs"].([]any)
|
||||
latest := logs[0].(map[string]any)
|
||||
if len(logs) != 9 || latest["operatorName"] != "leaf" || latest["logType"] != float64(2) || latest["attachments"].([]any)[0] != "/files/two.png" || data["alertRecord"].(map[string]any)["status"] != float64(5) {
|
||||
t.Fatalf("备注附件或状态错误: %+v", data)
|
||||
}
|
||||
call(99, "POST", "/sw/alertRecord/addNote", `{"alertId":"`+id+`","noteContent":"越权"}`, 7)
|
||||
call(1, "POST", "/sw/alertRecord/startProcess", `{"alertId":0}`, 7)
|
||||
if err := db.Exec("DROP TABLE tab_promote").Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data = list(8, "", 0)
|
||||
if data["available"] != false {
|
||||
t.Fatal("缺渠道表应报告未知范围")
|
||||
}
|
||||
call(8, "GET", detailPath, "", 7)
|
||||
process(9, "startProcess", "", 7)
|
||||
list(1, "", 6)
|
||||
}
|
||||
Generated
+6
-1
@@ -82,9 +82,13 @@ func wireApp(configServer *config.Server, store *config.Store, logger *slog.Logg
|
||||
auditRecorderUsecase := system2.NewAuditRecorderUsecase(auditRecordRepo)
|
||||
auditRecorder := system3.NewAuditRecorder(auditRecorderUsecase)
|
||||
registry := taskRegistry()
|
||||
alertRuleRepo := business.NewAlertRuleRepo(dataData)
|
||||
alertRecordRepo := business.NewAlertRecordRepo(dataData)
|
||||
accountRepo := business.NewAccountRepo(dataData)
|
||||
accountUsecase := business2.NewAccountUsecase(accountRepo)
|
||||
alertRecordUsecase := business2.NewAlertRecordUsecase(alertRecordRepo, accountUsecase)
|
||||
alertRecordService := business3.NewAlertRecordService(alertRecordUsecase)
|
||||
alertRecord := handler.NewAlertRecord(alertRecordService)
|
||||
alertRuleRepo := business.NewAlertRuleRepo(dataData)
|
||||
alertRuleUsecase := business2.NewAlertRuleUsecase(alertRuleRepo, accountUsecase)
|
||||
alertRuleService := business3.NewAlertRuleService(alertRuleUsecase)
|
||||
alertRule := handler.NewAlertRule(alertRuleService)
|
||||
@@ -205,6 +209,7 @@ func wireApp(configServer *config.Server, store *config.Store, logger *slog.Logg
|
||||
integrationConfigService := integration2.NewIntegrationConfigService(integrationConfigUsecase)
|
||||
integrationConfig := handler.NewIntegrationConfig(integrationConfigService)
|
||||
set := &handler.Set{
|
||||
AlertRecord: alertRecord,
|
||||
AlertRule: alertRule,
|
||||
BusinessPromote: businessPromote,
|
||||
Business: handlerBusiness,
|
||||
|
||||
Reference in New Issue
Block a user