Files
0451meishi/backend/internal/handlers/apikeys.go
2026-01-15 11:37:22 +08:00

91 lines
2.1 KiB
Go

package handlers
import (
"crypto/sha256"
"encoding/hex"
"net/http"
"strconv"
"strings"
"time"
"0451meishiditu/backend/internal/models"
"0451meishiditu/backend/internal/resp"
"github.com/gin-gonic/gin"
)
type apiKeyCreateReq struct {
Name string `json:"name" binding:"required"`
}
func (h *Handlers) APIKeyList(c *gin.Context) {
page, pageSize := parsePage(c.Query("page"), c.Query("page_size"))
q := h.db.Model(&models.APIKey{})
var total int64
if err := q.Count(&total).Error; err != nil {
resp.Fail(c, http.StatusInternalServerError, "db error")
return
}
var items []models.APIKey
if err := q.Order("id desc").Limit(pageSize).Offset((page - 1) * pageSize).Find(&items).Error; err != nil {
resp.Fail(c, http.StatusInternalServerError, "db error")
return
}
resp.OKMeta(c, items, gin.H{
"page": page,
"page_size": pageSize,
"total": total,
"total_page": calcTotalPage(total, pageSize),
})
}
func (h *Handlers) APIKeyCreate(c *gin.Context) {
var req apiKeyCreateReq
if err := c.ShouldBindJSON(&req); err != nil || strings.TrimSpace(req.Name) == "" {
resp.Fail(c, http.StatusBadRequest, "invalid payload")
return
}
plain := "ak_" + randomHex(24)
sum := sha256.Sum256([]byte(plain))
hash := hex.EncodeToString(sum[:])
prefix := plain
if len(prefix) > 10 {
prefix = prefix[:10]
}
item := models.APIKey{
Name: strings.TrimSpace(req.Name),
Prefix: prefix,
HashSHA256: hash,
Status: "active",
}
if err := h.db.Create(&item).Error; err != nil {
resp.Fail(c, http.StatusBadRequest, "create failed")
return
}
resp.OK(c, gin.H{
"id": item.ID,
"name": item.Name,
"prefix": item.Prefix,
"status": item.Status,
"key": plain, // 仅返回一次,前端应提示保存
})
}
func (h *Handlers) APIKeyRevoke(c *gin.Context) {
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
now := time.Now()
if err := h.db.Model(&models.APIKey{}).
Where("id = ? and status = 'active'", uint(id)).
Updates(map[string]any{"status": "revoked", "revoked_at": &now}).Error; err != nil {
resp.Fail(c, http.StatusInternalServerError, "revoke failed")
return
}
resp.OK(c, gin.H{"revoked": true})
}