72 lines
1.9 KiB
Go
72 lines
1.9 KiB
Go
package server
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
|
|
"code.littlelan.cn/CarrotAssistant/backend/internal/security"
|
|
"code.littlelan.cn/CarrotAssistant/backend/internal/store"
|
|
)
|
|
|
|
// RequireAppToken guards the public /api/v1 chat routes. It expects an
|
|
// X-App-Token header whose SHA-256 hash matches an App row. The matched App
|
|
// is placed on the context as "app".
|
|
func (d Deps) RequireAppToken() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
raw := strings.TrimSpace(c.GetHeader("X-App-Token"))
|
|
if raw == "" {
|
|
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "缺少 X-App-Token"})
|
|
return
|
|
}
|
|
hash := security.HashToken(raw)
|
|
var app store.App
|
|
err := d.DB.Where("token_hash = ? AND status = ?", hash, "active").First(&app).Error
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "无效的 token"})
|
|
return
|
|
}
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "查询失败"})
|
|
return
|
|
}
|
|
c.Set("app", &app)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// appCtx returns the App placed by RequireAppToken.
|
|
func appCtx(c *gin.Context) *store.App {
|
|
v, _ := c.Get("app")
|
|
if v == nil {
|
|
return nil
|
|
}
|
|
return v.(*store.App)
|
|
}
|
|
|
|
// createSession persists a new session row and returns it.
|
|
func (d Deps) createSession(appID int64, title string) (*store.Session, error) {
|
|
id, err := newUUID()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s := &store.Session{ID: id, AppID: appID, Title: title}
|
|
if err := d.DB.Create(s).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
// loadSessionOwnedBy returns a session only if it belongs to appID.
|
|
func (d Deps) loadSessionOwnedBy(sessionID string, appID int64) (*store.Session, error) {
|
|
var s store.Session
|
|
err := d.DB.Where("id = ? AND app_id = ?", sessionID, appID).First(&s).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &s, nil
|
|
}
|