初始提交:OCI 面板后端(含 GenAI 网关一期)
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"oci-portal/internal/service"
|
||||
)
|
||||
|
||||
// logEventHandler 处理回传事件查询与每租户回调地址管理(JWT 组内)。
|
||||
type logEventHandler struct {
|
||||
svc *service.LogEventService
|
||||
}
|
||||
|
||||
// getWebhook 查询配置的回调地址;未生成时 exists 为 false 且不含 secret。
|
||||
func (h *logEventHandler) getWebhook(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
info, exists, err := h.svc.SecretInfo(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
c.JSON(http.StatusOK, gin.H{"exists": false})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"exists": true, "webhook": info})
|
||||
}
|
||||
|
||||
// ensureWebhook 生成(或幂等返回)配置的回传 secret 与回调路径。
|
||||
func (h *logEventHandler) ensureWebhook(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
info, err := h.svc.EnsureSecret(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, info)
|
||||
}
|
||||
|
||||
// revokeWebhook 撤销配置的回传 secret,旧回调地址随即失效。
|
||||
func (h *logEventHandler) revokeWebhook(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if err := h.svc.RevokeSecret(c.Request.Context(), id); err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// list 分页查询回传事件;cfgId 缺省为全部租户。
|
||||
func (h *logEventHandler) list(c *gin.Context) {
|
||||
cfgID, _ := strconv.ParseUint(c.Query("cfgId"), 10, 64)
|
||||
page, _ := strconv.Atoi(c.Query("page"))
|
||||
pageSize, _ := strconv.Atoi(c.Query("pageSize"))
|
||||
items, total, err := h.svc.List(c.Request.Context(), service.LogEventQuery{
|
||||
CfgID: uint(cfgID),
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
})
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items, "total": total})
|
||||
}
|
||||
|
||||
// getRelay 查询 OCI 侧链路状态与关键事件清单。
|
||||
func (h *logEventHandler) getRelay(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
view, err := h.svc.RelayStatus(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
respondRelayError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, view)
|
||||
}
|
||||
|
||||
// setupRelay 一键建立回传链路(P1 引导创建);同步执行,前端以长超时等待。
|
||||
func (h *logEventHandler) setupRelay(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
view, err := h.svc.SetupRelay(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
respondRelayError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, view)
|
||||
}
|
||||
|
||||
// teardownRelay 逆序销毁链路并撤销 secret。
|
||||
func (h *logEventHandler) teardownRelay(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if err := h.svc.TeardownRelay(c.Request.Context(), id); err != nil {
|
||||
respondRelayError(c, err)
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// respondRelayError 在通用映射之上补充引导创建专属错误:依赖未配置映射 409。
|
||||
func respondRelayError(c *gin.Context, err error) {
|
||||
if errors.Is(err, service.ErrRelayNotConfigured) {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
respondError(c, err)
|
||||
}
|
||||
Reference in New Issue
Block a user