提交代码

This commit is contained in:
lmk
2026-07-02 10:37:59 +08:00
parent aced1aa3a6
commit d930266fbf
17 changed files with 411 additions and 445 deletions
@@ -7,9 +7,12 @@ import (
serviceDataengine "cid/service/dataengine"
"context"
"fmt"
"strings"
"time"
"gitea.redpowerfuture.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
// MaterialVerifyController 素材校验控制器
@@ -104,6 +107,8 @@ type BatchVerifyReq struct {
// ListImage 图片素材列表
func (c *MaterialVerifyController) ListImage(ctx context.Context, req *ImageListReq) (res *ImageListRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.Page == 0 {
req.Page = 1
}
@@ -132,6 +137,7 @@ func (c *MaterialVerifyController) ListImage(ctx context.Context, req *ImageList
// StatsImage 图片素材统计
func (c *MaterialVerifyController) StatsImage(ctx context.Context, req *ImageListReq) (res *StatsRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
// 使用实体中定义的正确状态值:PENDING=待校验, VERIFIED=校验通过, REJECTED=校验不通过
pending, _ := dao.TencentImage.CountByStatus(ctx, entity.VerifyStatusPending)
verified, _ := dao.TencentImage.CountByStatus(ctx, entity.VerifyStatusVerified)
@@ -150,6 +156,8 @@ func (c *MaterialVerifyController) StatsImage(ctx context.Context, req *ImageLis
// ListVideo 视频素材列表
func (c *MaterialVerifyController) ListVideo(ctx context.Context, req *VideoListReq) (res *VideoListRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.Page == 0 {
req.Page = 1
}
@@ -178,6 +186,7 @@ func (c *MaterialVerifyController) ListVideo(ctx context.Context, req *VideoList
// StatsVideo 视频素材统计
func (c *MaterialVerifyController) StatsVideo(ctx context.Context, req *VideoListReq) (res *StatsRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
// 使用实体中定义的正确状态值:PENDING=待校验, VERIFIED=校验通过, REJECTED=校验不通过
pending, _ := dao.TencentVideo.CountByStatus(ctx, entity.VerifyStatusPending)
verified, _ := dao.TencentVideo.CountByStatus(ctx, entity.VerifyStatusVerified)
@@ -202,6 +211,8 @@ type ListLogRes struct {
// ListLog 日志列表
func (c *MaterialVerifyController) ListLog(ctx context.Context, req *LogListReq) (res *ListLogRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.Page == 0 {
req.Page = 1
}
@@ -247,6 +258,8 @@ type GetLogDetailReq struct {
// GetLogDetail 日志详情
func (c *MaterialVerifyController) GetLogDetail(ctx context.Context, req *GetLogDetailReq) (res *LogDetailRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
log, err := serviceDataengine.MaterialVerify.GetLogByID(ctx, req.Id)
if err != nil {
return nil, err
@@ -284,6 +297,7 @@ type StatsLogRes struct {
// StatsLog 日志统计
func (c *MaterialVerifyController) StatsLog(ctx context.Context, req *LogListReq) (res *StatsLogRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
stats, err := serviceDataengine.MaterialVerify.GetStats(ctx)
if err != nil {
return nil, err
@@ -310,6 +324,8 @@ type ManualVerifyImageRes struct {
// ManualVerifyImage 手动校验图片
func (c *MaterialVerifyController) ManualVerifyImage(ctx context.Context, req *ManualVerifyReq) (res *ManualVerifyImageRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
log, err := serviceDataengine.MaterialVerify.VerifyImageByID(ctx, req.MaterialID)
if err != nil {
return nil, err
@@ -324,6 +340,8 @@ func (c *MaterialVerifyController) ManualVerifyImage(ctx context.Context, req *M
// ManualVerifyVideo 手动校验视频
func (c *MaterialVerifyController) ManualVerifyVideo(ctx context.Context, req *ManualVerifyReq) (res *ManualVerifyImageRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
log, err := serviceDataengine.MaterialVerify.VerifyVideoByID(ctx, req.MaterialID)
if err != nil {
return nil, err
@@ -350,6 +368,8 @@ type BatchVerifyRes struct {
// BatchVerifyImage 批量校验图片
func (c *MaterialVerifyController) BatchVerifyImage(ctx context.Context, req *BatchVerifyReq) (res *BatchVerifyRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.Limit <= 0 {
req.Limit = 100
}
@@ -363,37 +383,28 @@ func (c *MaterialVerifyController) BatchVerifyImage(ctx context.Context, req *Ba
failCount := 0
for _, image := range images {
log, err := serviceDataengine.MaterialVerify.VerifyImageByID(ctx, image.ImageID)
_, err := serviceDataengine.MaterialVerify.VerifyImageByID(ctx, image.ImageID)
if err != nil {
failCount++
g.Log().Errorf(ctx, "图片校验失败: %s, error: %v", image.ImageID, err)
} else {
successCount++
g.Log().Infof(ctx, "图片校验已提交: %s, logId: %d", image.ImageID, log.Id)
}
time.Sleep(100 * time.Millisecond)
}
// 等待易盾处理,然后自动查询结果
msg := fmt.Sprintf("批量校验完成,成功: %d,失败: %d", successCount, failCount)
if successCount > 0 {
g.Log().Infof(ctx, "提交完成,等待2秒后自动查询结果...")
time.Sleep(2 * time.Second)
pollSuccess, pollFail, _ := serviceDataengine.MaterialVerify.PollPendingResults(ctx)
msg = fmt.Sprintf("批量校验完成,提交成功: %d,提交失败: %d,自动查询成功: %d,未就绪: %d",
successCount, failCount, pollSuccess, pollFail)
}
return &BatchVerifyRes{
Success: successCount,
Fail: failCount,
Total: len(images),
Message: msg,
Message: fmt.Sprintf("批量提交完成,成功: %d,失败: %d。请通过轮询接口获取检测结果", successCount, failCount),
}, nil
}
// BatchVerifyVideo 批量校验视频
func (c *MaterialVerifyController) BatchVerifyVideo(ctx context.Context, req *BatchVerifyReq) (res *BatchVerifyRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.Limit <= 0 {
req.Limit = 100
}
@@ -407,32 +418,21 @@ func (c *MaterialVerifyController) BatchVerifyVideo(ctx context.Context, req *Ba
failCount := 0
for _, video := range videos {
log, err := serviceDataengine.MaterialVerify.VerifyVideoByID(ctx, video.VideoID)
_, err := serviceDataengine.MaterialVerify.VerifyVideoByID(ctx, video.VideoID)
if err != nil {
failCount++
g.Log().Errorf(ctx, "视频校验失败: %s, error: %v", video.VideoID, err)
} else {
successCount++
g.Log().Infof(ctx, "视频校验已提交: %s, logId: %d", video.VideoID, log.Id)
}
time.Sleep(100 * time.Millisecond)
}
// 等待易盾处理,然后自动查询结果
msg := fmt.Sprintf("批量校验完成,成功: %d,失败: %d", successCount, failCount)
if successCount > 0 {
g.Log().Infof(ctx, "提交完成,等待2秒后自动查询结果...")
time.Sleep(2 * time.Second)
pollSuccess, pollFail, _ := serviceDataengine.MaterialVerify.PollPendingResults(ctx)
msg = fmt.Sprintf("批量校验完成,提交成功: %d,提交失败: %d,自动查询成功: %d,未就绪: %d",
successCount, failCount, pollSuccess, pollFail)
}
return &BatchVerifyRes{
Success: successCount,
Fail: failCount,
Total: len(videos),
Message: msg,
Message: fmt.Sprintf("批量提交完成,成功: %d,失败: %d。请通过轮询接口获取检测结果", successCount, failCount),
}, nil
}
@@ -456,6 +456,7 @@ type ListAccountsRes struct {
// ListAccounts 获取所有启用的广告账户列表(用于前端下拉筛选)
func (c *MaterialVerifyController) ListAccounts(ctx context.Context, req *ListAccountsReq) (res *ListAccountsRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
accounts, err := dao.TencentAccountRelation.GetAll(ctx)
if err != nil {
return nil, err
@@ -505,6 +506,8 @@ type ExportRejectedRes struct {
// ExportRejected 导出不通过的图片/视频数据(含失败原因)
func (c *MaterialVerifyController) ExportRejected(ctx context.Context, req *ExportRejectedReq) (res *ExportRejectedRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
items, err := serviceDataengine.MaterialVerify.ExportRejectedData(ctx, req.MaterialType)
if err != nil {
return nil, err
@@ -543,8 +546,32 @@ type CallbackRes struct {
Msg string `json:"msg"`
}
// checkIP 校验请求IP是否在白名单内(context模式)
func checkIP(ctx context.Context) bool {
r := ghttp.RequestFromCtx(ctx)
if r == nil {
return true
}
allowedIPs := g.Cfg().MustGet(ctx, "yidun.callback_allowed_ips", "").String()
if allowedIPs == "" {
return true
}
clientIP := r.GetClientIp()
for _, ip := range strings.Split(allowedIPs, ",") {
if strings.TrimSpace(ip) == clientIP {
return true
}
}
g.Log().Warningf(ctx, "回调IP不在白名单中, clientIP=%s", clientIP)
return false
}
// ImageCallback 图片校验回调
func (c *MaterialVerifyController) ImageCallback(ctx context.Context, req *ImageCallbackReq) (res *CallbackRes, err error) {
if !checkIP(ctx) {
return &CallbackRes{Code: 403, Msg: "IP not allowed"}, nil
}
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "yidun_callback", TenantId: 1})
if req.CallbackData == "" {
return &CallbackRes{Code: 400, Msg: "callbackData不能为空"}, nil
}
@@ -559,6 +586,10 @@ func (c *MaterialVerifyController) ImageCallback(ctx context.Context, req *Image
// VideoCallback 视频校验回调
func (c *MaterialVerifyController) VideoCallback(ctx context.Context, req *VideoCallbackReq) (res *CallbackRes, err error) {
if !checkIP(ctx) {
return &CallbackRes{Code: 403, Msg: "IP not allowed"}, nil
}
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "yidun_callback", TenantId: 1})
if req.CallbackData == "" {
return &CallbackRes{Code: 400, Msg: "callbackData不能为空"}, nil
}
@@ -579,6 +610,7 @@ type ResultRes struct {
// ImageResult 图片校验结果查询(轮询模式)
func (c *MaterialVerifyController) ImageResult(ctx context.Context, req *TaskIDReq) (res *ResultRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.TaskID == "" {
return &ResultRes{Code: 400, Msg: "taskId不能为空"}, nil
}
@@ -593,6 +625,7 @@ func (c *MaterialVerifyController) ImageResult(ctx context.Context, req *TaskIDR
// VideoResult 视频校验结果查询(轮询模式)
func (c *MaterialVerifyController) VideoResult(ctx context.Context, req *TaskIDReq) (res *ResultRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.TaskID == "" {
return &ResultRes{Code: 400, Msg: "taskId不能为空"}, nil
}
+16 -15
View File
@@ -4,6 +4,7 @@ import (
dto "cid/model/dto/yidun"
serviceDataengine "cid/service/dataengine"
"context"
"fmt"
"gitea.redpowerfuture.com/red-future/common/beans"
)
@@ -23,7 +24,7 @@ type StatusRes struct {
// Start 启动送检服务
func (c *ContentCheckController) Start(ctx context.Context, req *dto.StartCheckReq) (res *beans.ResponseEmpty, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if serviceDataengine.TencentContentCheck.IsRunning() {
return &beans.ResponseEmpty{}, nil
@@ -49,14 +50,14 @@ func (c *ContentCheckController) Start(ctx context.Context, req *dto.StartCheckR
// Stop 停止送检服务
func (c *ContentCheckController) Stop(ctx context.Context, req *dto.EmptyReq) (res *beans.ResponseEmpty, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
serviceDataengine.TencentContentCheck.Stop(ctx)
return
}
// Status 获取送检服务状态
func (c *ContentCheckController) Status(ctx context.Context, req *dto.EmptyReq) (res *StatusRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
res = &StatusRes{
Running: serviceDataengine.TencentContentCheck.IsRunning(),
@@ -68,10 +69,10 @@ func (c *ContentCheckController) Status(ctx context.Context, req *dto.EmptyReq)
// ProcessImageCallback 处理图片检测回调
func (c *ContentCheckController) ProcessImageCallback(ctx context.Context, req *dto.ProcessImageCallbackReq) (res *beans.ResponseEmpty, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.CallbackData == "" {
return nil, err
return nil, fmt.Errorf("callbackData不能为空")
}
err = serviceDataengine.TencentContentCallback.ProcessImageCallback(ctx, req.CallbackData)
@@ -80,10 +81,10 @@ func (c *ContentCheckController) ProcessImageCallback(ctx context.Context, req *
// ProcessVideoCallback 处理视频检测回调
func (c *ContentCheckController) ProcessVideoCallback(ctx context.Context, req *dto.ProcessVideoCallbackReq) (res *beans.ResponseEmpty, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.CallbackData == "" {
return nil, err
return nil, fmt.Errorf("callbackData不能为空")
}
err = serviceDataengine.TencentContentCallback.ProcessVideoCallback(ctx, req.CallbackData)
@@ -92,10 +93,10 @@ func (c *ContentCheckController) ProcessVideoCallback(ctx context.Context, req *
// ProcessImageResult 查询并处理图片检测结果(轮询模式)
func (c *ContentCheckController) ProcessImageResult(ctx context.Context, req *dto.ProcessImageResultReq) (res *beans.ResponseEmpty, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.TaskID == "" {
return nil, err
return nil, fmt.Errorf("taskId不能为空")
}
err = serviceDataengine.TencentContentCallback.ProcessImageResult(ctx, req.TaskID)
@@ -104,10 +105,10 @@ func (c *ContentCheckController) ProcessImageResult(ctx context.Context, req *dt
// ProcessVideoResult 查询并处理视频检测结果(轮询模式)
func (c *ContentCheckController) ProcessVideoResult(ctx context.Context, req *dto.ProcessVideoResultReq) (res *beans.ResponseEmpty, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
if req.TaskID == "" {
return nil, err
return nil, fmt.Errorf("taskId不能为空")
}
err = serviceDataengine.TencentContentCallback.ProcessVideoResult(ctx, req.TaskID)
@@ -116,7 +117,7 @@ func (c *ContentCheckController) ProcessVideoResult(ctx context.Context, req *dt
// ManualSubmitImageByID 根据图片ID手动提交送检
func (c *ContentCheckController) ManualSubmitImageByID(ctx context.Context, req *dto.ManualSubmitImageByIDReq) (res *dto.ManualSubmitRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
result, err := serviceDataengine.TencentContentCheck.SubmitImageByID(ctx, req.ImageID)
if err != nil {
@@ -131,7 +132,7 @@ func (c *ContentCheckController) ManualSubmitImageByID(ctx context.Context, req
// ManualSubmitVideoByID 根据视频ID手动提交送检
func (c *ContentCheckController) ManualSubmitVideoByID(ctx context.Context, req *dto.ManualSubmitVideoByIDReq) (res *dto.ManualSubmitRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
result, err := serviceDataengine.TencentContentCheck.SubmitVideoByID(ctx, req.VideoID)
if err != nil {
@@ -146,7 +147,7 @@ func (c *ContentCheckController) ManualSubmitVideoByID(ctx context.Context, req
// GetImageCheckLogs 获取图片的送检日志
func (c *ContentCheckController) GetImageCheckLogs(ctx context.Context, req *dto.GetImageCheckLogsReq) (res *dto.GetCheckLogsRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
logs, err := serviceDataengine.TencentContentCallback.GetCheckLogsByImageID(ctx, req.ImageID)
if err != nil {
@@ -161,7 +162,7 @@ func (c *ContentCheckController) GetImageCheckLogs(ctx context.Context, req *dto
// GetVideoCheckLogs 获取视频的送检日志
func (c *ContentCheckController) GetVideoCheckLogs(ctx context.Context, req *dto.GetVideoCheckLogsReq) (res *dto.GetCheckLogsRes, err error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
logs, err := serviceDataengine.TencentContentCallback.GetCheckLogsByVideoID(ctx, req.VideoID)
if err != nil {
+38 -9
View File
@@ -4,6 +4,7 @@ import (
dataengineService "cid/service/dataengine"
"context"
"fmt"
"strings"
"gitea.redpowerfuture.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
@@ -40,8 +41,14 @@ type PollResult struct {
// 易盾回调格式: POST /yidun/callback/receiveImage
// Body: callbackData={"antispam":{...}}
func (c *YidunCallbackController) ReceiveImageCallback(r *ghttp.Request) {
// IP 白名单校验
if !checkCallbackIP(r) {
r.Response.WriteJson(CallbackResult{Code: 403, Msg: "IP not allowed"})
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "yidun_callback"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "yidun_callback", TenantId: 1})
// 易盾推送的数据在请求体中
var callbackData string
@@ -86,8 +93,14 @@ func (c *YidunCallbackController) ReceiveImageCallback(r *ghttp.Request) {
// 易盾回调格式: POST /yidun/callback/receiveVideo
// Body: callbackData={"antispam":{...}}
func (c *YidunCallbackController) ReceiveVideoCallback(r *ghttp.Request) {
// IP 白名单校验
if !checkCallbackIP(r) {
r.Response.WriteJson(CallbackResult{Code: 403, Msg: "IP not allowed"})
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "yidun_callback"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "yidun_callback", TenantId: 1})
// 易盾推送的数据在请求体中
var callbackData string
@@ -136,7 +149,7 @@ func (c *YidunCallbackController) ReceiveVideoCallback(r *ghttp.Request) {
// 格式: POST /yidun/callback/poll
func (c *YidunCallbackController) PollAllResults(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
g.Log().Info(ctx, "开始轮询所有待查询的检测结果...")
@@ -172,7 +185,7 @@ func (c *YidunCallbackController) PollAllResults(r *ghttp.Request) {
// 格式: POST /yidun/callback/pollImage
func (c *YidunCallbackController) PollImageResults(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
g.Log().Info(ctx, "开始轮询图片待查询的检测结果...")
@@ -198,7 +211,7 @@ func (c *YidunCallbackController) PollImageResults(r *ghttp.Request) {
// 格式: POST /yidun/callback/pollVideo
func (c *YidunCallbackController) PollVideoResults(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
g.Log().Info(ctx, "开始轮询视频待查询的检测结果...")
@@ -224,7 +237,7 @@ func (c *YidunCallbackController) PollVideoResults(r *ghttp.Request) {
// 格式: POST /yidun/callback/pollTask
func (c *YidunCallbackController) PollByTaskID(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
taskID := r.Get("taskId", "").String()
taskType := r.Get("type", "").String() // image 或 video
@@ -262,7 +275,7 @@ func (c *YidunCallbackController) PollByTaskID(r *ghttp.Request) {
// 格式: GET /yidun/callback/pendingCount
func (c *YidunCallbackController) GetPendingCount(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
count, err := dataengineService.MaterialVerify.GetPendingResultsCount(ctx)
if err != nil {
@@ -287,7 +300,7 @@ func (c *YidunCallbackController) GetPendingCount(r *ghttp.Request) {
// 格式: POST /yidun/callback/processImage
func (c *YidunCallbackController) ProcessImageCallback(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
var req struct {
CallbackData string `json:"callbackData" v:"required#回调数据不能为空"`
@@ -311,7 +324,7 @@ func (c *YidunCallbackController) ProcessImageCallback(r *ghttp.Request) {
// 格式: POST /yidun/callback/processVideo
func (c *YidunCallbackController) ProcessVideoCallback(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
var req struct {
CallbackData string `json:"callbackData" v:"required#回调数据不能为空"`
@@ -338,3 +351,19 @@ func toString(v interface{}) string {
}
return ""
}
// checkCallbackIP 校验回调请求IP是否在白名单内
func checkCallbackIP(r *ghttp.Request) bool {
allowedIPs := g.Cfg().MustGet(r.Context(), "yidun.callback_allowed_ips", "").String()
if allowedIPs == "" {
return true // 未配置白名单,跳过校验
}
clientIP := r.GetClientIp()
for _, ip := range strings.Split(allowedIPs, ",") {
if strings.TrimSpace(ip) == clientIP {
return true
}
}
g.Log().Warningf(r.Context(), "回调IP不在白名单中, clientIP=%s, allowedIPs=%s", clientIP, allowedIPs)
return false
}
+19 -7
View File
@@ -39,7 +39,7 @@ type DetectVideoReq struct {
// DetectText 文本检测
func (c *yidunController) DetectText(ctx context.Context, req *DetectTextReq) (string, error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
businessId := g.Cfg().MustGet(ctx, "yidun.text.business_id").String()
sdkReq := single.NewTextAsyncCheckRequest(businessId)
@@ -57,13 +57,13 @@ func (c *yidunController) DetectText(ctx context.Context, req *DetectTextReq) (s
// DetectImage 图片检测
func (c *yidunController) DetectImage(ctx context.Context, req *DetectImageReq) (*yidun.ImageSubmitResult, error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
return yidun.ImageDetection.DetectImage(ctx, req.ImageURL, req.DataID, req.CallbackURL)
}
// DetectVideo 视频检测
func (c *yidunController) DetectVideo(ctx context.Context, req *DetectVideoReq) (*yidun.VideoSubmitResult, error) {
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
return yidun.VideoDetection.DetectVideo(ctx, req.VideoURL, req.DataID, req.CallbackURL)
}
@@ -75,8 +75,14 @@ type ImageCallbackResult struct {
// ReceiveImageCallback 接收图片检测结果推送
func (c *yidunController) ReceiveImageCallback(r *ghttp.Request) {
// IP 白名单校验
if !checkCallbackIP(r) {
r.Response.WriteJson(ImageCallbackResult{Code: 403, Msg: "IP not allowed"})
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
callbackData := r.GetForm("callbackData", "").String()
if callbackData == "" {
@@ -102,8 +108,14 @@ type VideoCallbackResult struct {
// ReceiveVideoCallback 接收视频检测结果推送
func (c *yidunController) ReceiveVideoCallback(r *ghttp.Request) {
// IP 白名单校验
if !checkCallbackIP(r) {
r.Response.WriteJson(VideoCallbackResult{Code: 403, Msg: "IP not allowed"})
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
callbackData := r.GetForm("callbackData", "").String()
if callbackData == "" {
@@ -124,7 +136,7 @@ func (c *yidunController) ReceiveVideoCallback(r *ghttp.Request) {
// GetVideoResult 获取视频检测结果
func (c *yidunController) GetVideoResult(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
taskId := r.Get("taskId", "").String()
if taskId == "" {
@@ -145,7 +157,7 @@ func (c *yidunController) GetVideoResult(r *ghttp.Request) {
// GetImageResult 获取图片检测结果
func (c *yidunController) GetImageResult(r *ghttp.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
taskId := r.Get("taskId", "").String()
if taskId == "" {