server: Go 服务器(REST+WSS 网关+JWT+Argon2+配对+素材直链+任务状态机);修复并发下线 send-on-closed-channel、下发查询 SQL 优先级、配对码原子占用、上传体积上限、JWT 默认密钥告警
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"everypublish/server/internal/api/response"
|
||||
"everypublish/server/internal/models"
|
||||
)
|
||||
|
||||
// ChallengeHandler 二次验证挑战处理器
|
||||
type ChallengeHandler struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
// List 挑战列表(过期软置 expired)
|
||||
func (h *ChallengeHandler) List(c *gin.Context) {
|
||||
h.DB.Model(&models.Challenge{}).
|
||||
Where("workspace_id = ? and status = ? and expires_at < ?", c.GetUint64("wsid"), "active", time.Now()).
|
||||
Update("status", "expired")
|
||||
q := h.DB.Model(&models.Challenge{}).Where("workspace_id = ?", c.GetUint64("wsid"))
|
||||
if s := c.Query("status"); s != "" {
|
||||
q = q.Where("status = ?", s)
|
||||
}
|
||||
if a := c.Query("accountId"); a != "" {
|
||||
q = q.Where("account_id = ?", a)
|
||||
}
|
||||
var list []models.Challenge
|
||||
q.Order("id desc").Limit(100).Find(&list)
|
||||
response.OK(c, gin.H{"list": list})
|
||||
}
|
||||
|
||||
// Solve 人工完成挑战(验证码/APP确认;扫码由 Agent 完成)
|
||||
func (h *ChallengeHandler) Solve(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.Fail(c, http.StatusBadRequest, 1001, "参数不合法")
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
Value string `json:"value"`
|
||||
}
|
||||
_ = c.ShouldBindJSON(&req)
|
||||
var challenge models.Challenge
|
||||
if err = h.DB.Where("id = ? and workspace_id = ?", id, c.GetUint64("wsid")).First(&challenge).Error; err != nil {
|
||||
response.Fail(c, http.StatusNotFound, 1004, "挑战不存在")
|
||||
return
|
||||
}
|
||||
if challenge.Status != "active" {
|
||||
response.Fail(c, http.StatusConflict, 3003, "挑战已结束")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
if err = h.DB.Model(&challenge).Updates(map[string]interface{}{"status": "solved", "solved_at": &now}).Error; err != nil {
|
||||
response.Fail(c, http.StatusInternalServerError, 5000, "更新失败")
|
||||
return
|
||||
}
|
||||
response.Audit(c, "challenge.solve", "challenge:"+itoa(id), gin.H{"kind": challenge.Kind})
|
||||
response.OK(c, nil)
|
||||
}
|
||||
|
||||
// Resend 一键重发(重置过期时间,实际重发出 Agent 执行)
|
||||
func (h *ChallengeHandler) Resend(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.Fail(c, http.StatusBadRequest, 1001, "参数不合法")
|
||||
return
|
||||
}
|
||||
var challenge models.Challenge
|
||||
if err = h.DB.Where("id = ? and workspace_id = ?", id, c.GetUint64("wsid")).First(&challenge).Error; err != nil {
|
||||
response.Fail(c, http.StatusNotFound, 1004, "挑战不存在")
|
||||
return
|
||||
}
|
||||
if challenge.Status != "expired" && challenge.Status != "suspended" {
|
||||
response.Fail(c, http.StatusConflict, 3003, "当前状态不可重发")
|
||||
return
|
||||
}
|
||||
if err = h.DB.Model(&challenge).Updates(map[string]interface{}{
|
||||
"status": "active", "expires_at": time.Now().Add(30 * time.Minute),
|
||||
}).Error; err != nil {
|
||||
response.Fail(c, http.StatusInternalServerError, 5000, "更新失败")
|
||||
return
|
||||
}
|
||||
response.Audit(c, "challenge.resend", "challenge:"+itoa(id), nil)
|
||||
response.OK(c, nil)
|
||||
}
|
||||
|
||||
// Suspend 挂起(超时/人工)
|
||||
func (h *ChallengeHandler) Suspend(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.Fail(c, http.StatusBadRequest, 1001, "参数不合法")
|
||||
return
|
||||
}
|
||||
var challenge models.Challenge
|
||||
if err = h.DB.Where("id = ? and workspace_id = ?", id, c.GetUint64("wsid")).First(&challenge).Error; err != nil {
|
||||
response.Fail(c, http.StatusNotFound, 1004, "挑战不存在")
|
||||
return
|
||||
}
|
||||
if challenge.Status != "active" {
|
||||
response.Fail(c, http.StatusConflict, 3003, "挑战已结束")
|
||||
return
|
||||
}
|
||||
if err = h.DB.Model(&challenge).Update("status", "suspended").Error; err != nil {
|
||||
response.Fail(c, http.StatusInternalServerError, 5000, "更新失败")
|
||||
return
|
||||
}
|
||||
response.Audit(c, "challenge.suspend", "challenge:"+itoa(id), nil)
|
||||
response.OK(c, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user