mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-05 15:26:36 +08:00
fix(idgen): retry snowflake generation and error on negative ID
NextUint64ID now retries up to 3 times when Int64() is negative, then returns an error instead of 0 or Fatalf. All call sites propagate the error to avoid GORM omitting zero-value primary keys.
This commit is contained in:
@@ -4,7 +4,8 @@
|
||||
|
||||
package user
|
||||
|
||||
import ("net/http"
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -17,7 +18,8 @@ import ("net/http"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/common/response")
|
||||
"github.com/Rain-kl/Wavelet/internal/common/response"
|
||||
)
|
||||
|
||||
// minPasswordLength 密码最小长度
|
||||
const minPasswordLength = 8
|
||||
@@ -31,7 +33,7 @@ type listUsersRequest struct {
|
||||
}
|
||||
|
||||
type user struct {
|
||||
ID uint64 `json:"id"`
|
||||
ID uint64 `json:"id,string"`
|
||||
Username string `json:"username"`
|
||||
Nickname string `json:"nickname"`
|
||||
Email string `json:"email"`
|
||||
@@ -104,7 +106,7 @@ func ListUsers(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var users []user
|
||||
var modelUsers []model.User
|
||||
var total int64
|
||||
|
||||
query := db.DB(c.Request.Context()).Model(&model.User{})
|
||||
@@ -131,11 +133,16 @@ func ListUsers(c *gin.Context) {
|
||||
Order("id DESC").
|
||||
Offset(offset).
|
||||
Limit(req.PageSize).
|
||||
Find(&users).Error; err != nil {
|
||||
Find(&modelUsers).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
users := make([]user, 0, len(modelUsers))
|
||||
for _, modelUser := range modelUsers {
|
||||
users = append(users, toUser(modelUser))
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.OK(listUsersResponse{
|
||||
Users: users,
|
||||
Total: total,
|
||||
@@ -379,8 +386,14 @@ func CreateUser(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
nextID, err := idgen.NextUint64ID()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(createUserFailed))
|
||||
return
|
||||
}
|
||||
|
||||
newUser := model.User{
|
||||
ID: idgen.NextUint64ID(),
|
||||
ID: nextID,
|
||||
Username: req.Username,
|
||||
Nickname: req.Nickname,
|
||||
Email: req.Email,
|
||||
|
||||
@@ -4,18 +4,20 @@
|
||||
// Package risk_control 提供风险控制中间件
|
||||
package risk_control
|
||||
|
||||
import ("encoding/json"
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/apps/oauth"
|
||||
"github.com/Rain-kl/Wavelet/internal/common/response"
|
||||
"github.com/Rain-kl/Wavelet/internal/config"
|
||||
"github.com/Rain-kl/Wavelet/internal/db/idgen"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
"github.com/Rain-kl/Wavelet/internal/util"
|
||||
"github.com/Rain-kl/Wavelet/pkg/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/common/response")
|
||||
)
|
||||
|
||||
// RiskControlMiddleware 全局日志采集中间件
|
||||
func RiskControlMiddleware() gin.HandlerFunc {
|
||||
@@ -68,8 +70,14 @@ func RiskControlMiddleware() gin.HandlerFunc {
|
||||
status = maxHTTPStatus
|
||||
}
|
||||
|
||||
logID, err := idgen.NextUint64ID()
|
||||
if err != nil {
|
||||
logger.ErrorF(c.Request.Context(), "[RiskControl] access log ID generation failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
logItem := &UserAccessLog{
|
||||
ID: idgen.NextUint64ID(),
|
||||
ID: logID,
|
||||
UserID: userObj.ID, // 直接从 Context 获取已登录用户ID,避免数据库查询
|
||||
Path: c.Request.URL.Path,
|
||||
Method: c.Request.Method,
|
||||
|
||||
@@ -117,21 +117,10 @@ func UploadFile(c *gin.Context) {
|
||||
|
||||
uploadType := c.DefaultPostForm("type", "generic")
|
||||
|
||||
accessModeStr := c.PostForm("access_mode")
|
||||
var accessMode int
|
||||
if accessModeStr == "" {
|
||||
if uploadType == defaultPublicUploadType {
|
||||
accessMode = 1
|
||||
} else {
|
||||
accessMode = 0
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
accessMode, err = strconv.Atoi(accessModeStr)
|
||||
if err != nil || (accessMode != 0 && accessMode != 1) {
|
||||
c.JSON(http.StatusOK, response.Err("无效的 access_mode 参数"))
|
||||
return
|
||||
}
|
||||
accessMode, errMsg := resolveUploadAccessMode(c, uploadType)
|
||||
if errMsg != "" {
|
||||
c.JSON(http.StatusOK, response.Err(errMsg))
|
||||
return
|
||||
}
|
||||
|
||||
// 6. 秒传匹配校验:校验数据库中是否存在相同 Hash 且大小一致的可用文件
|
||||
@@ -151,7 +140,11 @@ func UploadFile(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
id := idgen.NextUint64ID()
|
||||
id, err := idgen.NextUint64ID()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, response.Err(ErrSaveUploadRecordFailed))
|
||||
return
|
||||
}
|
||||
subPath := fmt.Sprintf("uploads/%s/%d.%s", time.Now().Format("2006/01/02"), id, ext)
|
||||
|
||||
// 8. 写入当前活动存储驱动。
|
||||
@@ -336,6 +329,22 @@ func BatchDownloadFiles(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func resolveUploadAccessMode(c *gin.Context, uploadType string) (int, string) {
|
||||
accessModeStr := c.PostForm("access_mode")
|
||||
if accessModeStr == "" {
|
||||
if uploadType == defaultPublicUploadType {
|
||||
return 1, ""
|
||||
}
|
||||
return 0, ""
|
||||
}
|
||||
|
||||
accessMode, err := strconv.Atoi(accessModeStr)
|
||||
if err != nil || (accessMode != 0 && accessMode != 1) {
|
||||
return 0, "无效的 access_mode 参数"
|
||||
}
|
||||
return accessMode, ""
|
||||
}
|
||||
|
||||
// validateUploadExtension 校验文件后缀是否在系统允许的上传扩展名列表中
|
||||
func validateUploadExtension(ctx context.Context, ext string) string {
|
||||
var sc model.SystemConfig
|
||||
@@ -367,7 +376,11 @@ func tryInstantUpload(ctx context.Context, c *gin.Context, currUser *model.User,
|
||||
return true, nil
|
||||
}
|
||||
|
||||
id := idgen.NextUint64ID()
|
||||
id, err := idgen.NextUint64ID()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, response.Err(ErrSaveUploadRecordFailed))
|
||||
return true, err
|
||||
}
|
||||
newUpload := model.Upload{
|
||||
ID: id,
|
||||
UserID: currUser.ID,
|
||||
|
||||
@@ -228,8 +228,14 @@ func Register(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
nextID, err := idgen.NextUint64ID()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
user := model.User{
|
||||
ID: idgen.NextUint64ID(),
|
||||
ID: nextID,
|
||||
Username: req.Username,
|
||||
Nickname: req.Nickname,
|
||||
Email: req.Email,
|
||||
|
||||
Reference in New Issue
Block a user