Files
SproutGate/sproutgate-backend/internal/handlers/helpers.go

81 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"crypto/rand"
"crypto/sha256"
"crypto/subtle"
"encoding/hex"
"fmt"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"sproutgate-backend/internal/auth"
"sproutgate-backend/internal/models"
)
func bearerToken(header string) string {
if header == "" {
return ""
}
if strings.HasPrefix(strings.ToLower(header), "bearer ") {
return strings.TrimSpace(header[7:])
}
return ""
}
func adminTokenFromRequest(c *gin.Context) string {
if token := strings.TrimSpace(c.Query("token")); token != "" {
return token
}
if token := strings.TrimSpace(c.GetHeader("X-Admin-Token")); token != "" {
return token
}
authHeader := strings.TrimSpace(c.GetHeader("Authorization"))
return bearerToken(authHeader)
}
func generateVerificationCode() (string, error) {
randomBytes := make([]byte, 3)
if _, err := rand.Read(randomBytes); err != nil {
return "", err
}
number := int(randomBytes[0])<<16 | int(randomBytes[1])<<8 | int(randomBytes[2])
return fmt.Sprintf("%06d", number%1000000), nil
}
func hashCode(code string) string {
sum := sha256.Sum256([]byte(code))
return hex.EncodeToString(sum[:])
}
func verifyCode(code string, hash string) bool {
return subtle.ConstantTimeCompare([]byte(hashCode(code)), []byte(hash)) == 1
}
func writeBanJSON(c *gin.Context, reason string) {
h := gin.H{"error": "account is banned", "valid": false}
if r := strings.TrimSpace(reason); r != "" {
h["banReason"] = r
}
c.JSON(http.StatusForbidden, h)
}
// abortIfTokenEpochStale 若 JWT 内 epoch 与用户当前 token_epoch 不一致,则拒绝(例如管理员已封禁并递增 epoch
func abortIfTokenEpochStale(c *gin.Context, claims *auth.Claims, u models.UserRecord) bool {
if claims.TokenEpoch == u.TokenEpoch {
return false
}
c.JSON(http.StatusUnauthorized, gin.H{"valid": false, "error": "token revoked"})
return true
}
func abortIfUserBanned(c *gin.Context, u models.UserRecord) bool {
if !u.Banned {
return false
}
writeBanJSON(c, u.BanReason)
return true
}