mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 04:17:23 +00:00
Move request limiter to middleware.
This commit is contained in:
@@ -3,11 +3,9 @@ package service
|
||||
import (
|
||||
"nysoure/server/dao"
|
||||
"nysoure/server/model"
|
||||
"nysoure/server/utils"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v3/log"
|
||||
)
|
||||
@@ -19,10 +17,6 @@ const (
|
||||
maxCommentBriefLength = 256 // Maximum length of a comment brief
|
||||
)
|
||||
|
||||
var (
|
||||
commentsLimiter = utils.NewRequestLimiter(maxCommentsPerIP, 24*time.Hour)
|
||||
)
|
||||
|
||||
type CommentRequest struct {
|
||||
Content string `json:"content"` // markdown
|
||||
// Images []uint `json:"images"` // Unrequired after new design
|
||||
@@ -62,11 +56,6 @@ func findImagesInContent(content string, host string) []uint {
|
||||
}
|
||||
|
||||
func CreateComment(req CommentRequest, userID uint, refID uint, ip string, cType model.CommentType, host string) (*model.CommentView, error) {
|
||||
if !commentsLimiter.AllowRequest(ip) {
|
||||
log.Warnf("IP %s has exceeded the comment limit of %d comments per day", ip, maxCommentsPerIP)
|
||||
return nil, model.NewRequestError("Too many comments from this IP address, please try again later")
|
||||
}
|
||||
|
||||
if len(req.Content) == 0 {
|
||||
return nil, model.NewRequestError("Content cannot be empty")
|
||||
}
|
||||
|
@@ -13,7 +13,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v3/log"
|
||||
@@ -25,23 +24,6 @@ const (
|
||||
storageKeyUnavailable = "storage_key_unavailable" // Placeholder for unavailable storage key
|
||||
)
|
||||
|
||||
var (
|
||||
ipDownloads = sync.Map{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
go func() {
|
||||
for {
|
||||
// Clean up old IP download records every 24 hours
|
||||
time.Sleep(24 * time.Hour)
|
||||
ipDownloads.Range(func(key, value interface{}) bool {
|
||||
ipDownloads.Delete(key)
|
||||
return true
|
||||
})
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func getUploadingSize() int64 {
|
||||
return dao.GetStatistic("uploading_size")
|
||||
}
|
||||
@@ -405,7 +387,7 @@ func GetFile(fid string) (*model.FileView, error) {
|
||||
}
|
||||
|
||||
// DownloadFile handles the file download request. Return a presigned URL or a direct file path.
|
||||
func DownloadFile(ip, fid, cfToken string) (string, string, error) {
|
||||
func DownloadFile(fid, cfToken string) (string, string, error) {
|
||||
passed, err := verifyCfToken(cfToken)
|
||||
if err != nil {
|
||||
log.Error("failed to verify cf token: ", err)
|
||||
@@ -415,17 +397,6 @@ func DownloadFile(ip, fid, cfToken string) (string, string, error) {
|
||||
log.Info("cf token verification failed")
|
||||
return "", "", model.NewRequestError("cf token verification failed")
|
||||
}
|
||||
log.Info("File download request from: " + ip)
|
||||
downloads, _ := ipDownloads.Load(ip)
|
||||
if downloads == nil {
|
||||
ipDownloads.Store(ip, 1)
|
||||
} else {
|
||||
count := downloads.(int)
|
||||
if count >= config.MaxDownloadsPerDayForSingleIP() {
|
||||
return "", "", model.NewRequestError("Too many requests, please try again later")
|
||||
}
|
||||
ipDownloads.Store(ip, count+1)
|
||||
}
|
||||
file, err := dao.GetFile(fid)
|
||||
if err != nil {
|
||||
log.Error("failed to get file: ", err)
|
||||
|
@@ -3,7 +3,6 @@ package service
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"github.com/disintegration/imaging"
|
||||
"image"
|
||||
"math"
|
||||
"net/http"
|
||||
@@ -14,14 +13,17 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
|
||||
"github.com/gofiber/fiber/v3/log"
|
||||
"github.com/google/uuid"
|
||||
|
||||
_ "golang.org/x/image/bmp"
|
||||
_ "image/gif"
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
|
||||
_ "golang.org/x/image/bmp"
|
||||
|
||||
_ "golang.org/x/image/webp"
|
||||
|
||||
"github.com/chai2010/webp"
|
||||
@@ -54,24 +56,12 @@ func init() {
|
||||
}()
|
||||
}
|
||||
|
||||
var (
|
||||
imageLimiter = utils.NewRequestLimiter(maxUploadsPerIP, 24*time.Hour)
|
||||
)
|
||||
|
||||
const maxUploadsPerIP = 100
|
||||
|
||||
func CreateImage(uid uint, ip string, data []byte) (uint, error) {
|
||||
canUpload, err := checkUserCanUpload(uid)
|
||||
if err != nil {
|
||||
log.Error("Error checking user upload permission:", err)
|
||||
return 0, model.NewInternalServerError("Error checking user upload permission")
|
||||
}
|
||||
if !canUpload {
|
||||
// For a normal user, check the IP upload limit
|
||||
if !imageLimiter.AllowRequest(ip) {
|
||||
return 0, model.NewUnAuthorizedError("You have reached the maximum upload limit")
|
||||
}
|
||||
}
|
||||
|
||||
if len(data) == 0 {
|
||||
return 0, model.NewRequestError("Image data is empty")
|
||||
|
@@ -3,7 +3,6 @@ package service
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gofiber/fiber/v3/log"
|
||||
"nysoure/server/config"
|
||||
"nysoure/server/dao"
|
||||
"nysoure/server/model"
|
||||
@@ -15,6 +14,8 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/gofiber/fiber/v3/log"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
@@ -376,7 +377,7 @@ func validateUsername(username string) error {
|
||||
if usernameLen < 3 || usernameLen > 20 {
|
||||
return model.NewRequestError("Username must be between 3 and 20 characters")
|
||||
}
|
||||
for _, r := range []rune(username) {
|
||||
for _, r := range username {
|
||||
if r == ' ' || r == '\n' || r == '\r' || r == '\t' || r == '\v' || r == '\f' {
|
||||
return model.NewRequestError("Username cannot contain whitespace characters")
|
||||
}
|
||||
|
Reference in New Issue
Block a user