Skip to content

Commit

Permalink
chore: merge branch 'main' of github.com:songquanpeng/gin-react-template
Browse files Browse the repository at this point in the history
  • Loading branch information
songquanpeng committed Nov 1, 2022
2 parents 2e7e9e4 + 5d5c657 commit 76d1455
Show file tree
Hide file tree
Showing 30 changed files with 861 additions and 615 deletions.
89 changes: 21 additions & 68 deletions common/constants.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package common

import (
"flag"
"fmt"
"github.com/google/uuid"
"os"
"path"
"path/filepath"
"sync"
"time"
)
Expand All @@ -16,6 +11,9 @@ var Version = "v0.0.0"
var SystemName = "项目模板"
var ServerAddress = "http://localhost:3000"

var SessionSecret = uuid.New().String()
var SQLitePath = ".gin-template.db"

var OptionMap map[string]string
var OptionMapRWMutex sync.RWMutex

Expand Down Expand Up @@ -47,73 +45,28 @@ var (
ImageDownloadPermission = RoleGuestUser
)

// All duration's unit is seconds
// Shouldn't larger then RateLimitKeyExpirationDuration
var (
GlobalApiRateLimit = 20
GlobalWebRateLimit = 60
UploadRateLimit = 10
DownloadRateLimit = 10
CriticalRateLimit = 3
)
GlobalApiRateLimitNum = 20
GlobalApiRateLimitDuration int64 = 60

const (
UserStatusEnabled = 1 // don't use 0, 0 is the default value!
UserStatusDisabled = 2 // also don't use 0
)
GlobalWebRateLimitNum = 20
GlobalWebRateLimitDuration int64 = 60

var (
Port = flag.Int("port", 3000, "specify the server listening port.")
Host = flag.String("host", "localhost", "the server's ip address or domain")
Path = flag.String("path", "", "specify a local path to public")
VideoPath = flag.String("video", "", "specify a video folder to public")
NoBrowser = flag.Bool("no-browser", false, "open browser or not")
PrintVersion = flag.Bool("version", false, "print version")
)
UploadRateLimitNum = 10
UploadRateLimitDuration int64 = 60

// UploadPath Maybe override by ENV_VAR
var UploadPath = "upload"
var ExplorerRootPath = UploadPath
var ImageUploadPath = "upload/images"
var VideoServePath = "upload"
DownloadRateLimitNum = 10
DownloadRateLimitDuration int64 = 60

var SessionSecret = uuid.New().String()
CriticalRateLimitNum = 5
CriticalRateLimitDuration int64 = 10 * 60
)

var SQLitePath = ".gin-template.db"
var RateLimitKeyExpirationDuration = 20 * time.Minute

func init() {
flag.Parse()

if *PrintVersion {
fmt.Println(Version)
os.Exit(0)
}

if os.Getenv("SESSION_SECRET") != "" {
SessionSecret = os.Getenv("SESSION_SECRET")
}
if os.Getenv("SQLITE_PATH") != "" {
SQLitePath = os.Getenv("SQLITE_PATH")
}
if os.Getenv("UPLOAD_PATH") != "" {
UploadPath = os.Getenv("UPLOAD_PATH")
ExplorerRootPath = UploadPath
ImageUploadPath = path.Join(UploadPath, "images")
VideoServePath = UploadPath
}
if *Path != "" {
ExplorerRootPath = *Path
}
if *VideoPath != "" {
VideoServePath = *VideoPath
}

ExplorerRootPath, _ = filepath.Abs(ExplorerRootPath)
VideoServePath, _ = filepath.Abs(VideoServePath)
ImageUploadPath, _ = filepath.Abs(ImageUploadPath)

if _, err := os.Stat(UploadPath); os.IsNotExist(err) {
_ = os.Mkdir(UploadPath, 0777)
}
if _, err := os.Stat(ImageUploadPath); os.IsNotExist(err) {
_ = os.Mkdir(ImageUploadPath, 0777)
}
}
const (
UserStatusEnabled = 1 // don't use 0, 0 is the default value!
UserStatusDisabled = 2 // also don't use 0
)
62 changes: 62 additions & 0 deletions common/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package common

import (
"flag"
"fmt"
"os"
)

var (
Port = flag.Int("port", 3000, "the listening port")
PrintVersion = flag.Bool("version", false, "print version and exit")
//Host = flag.String("host", "localhost", "the server's ip address or domain")
//Path = flag.String("path", "", "specify a local path to public")
//VideoPath = flag.String("video", "", "specify a video folder to public")
//NoBrowser = flag.Bool("no-browser", false, "open browser or not")
)

// UploadPath Maybe override by ENV_VAR
var UploadPath = "upload"

//var ExplorerRootPath = UploadPath
//var ImageUploadPath = "upload/images"
//var VideoServePath = "upload"

func init() {
flag.Parse()

if *PrintVersion {
fmt.Println(Version)
os.Exit(0)
}

if os.Getenv("SESSION_SECRET") != "" {
SessionSecret = os.Getenv("SESSION_SECRET")
}
if os.Getenv("SQLITE_PATH") != "" {
SQLitePath = os.Getenv("SQLITE_PATH")
}
if os.Getenv("UPLOAD_PATH") != "" {
UploadPath = os.Getenv("UPLOAD_PATH")
//ExplorerRootPath = UploadPath
//ImageUploadPath = path.Join(UploadPath, "images")
//VideoServePath = UploadPath
}
//if *Path != "" {
// ExplorerRootPath = *Path
//}
//if *VideoPath != "" {
// VideoServePath = *VideoPath
//}
//
//ExplorerRootPath, _ = filepath.Abs(ExplorerRootPath)
//VideoServePath, _ = filepath.Abs(VideoServePath)
//ImageUploadPath, _ = filepath.Abs(ImageUploadPath)
//
if _, err := os.Stat(UploadPath); os.IsNotExist(err) {
_ = os.Mkdir(UploadPath, 0777)
}
//if _, err := os.Stat(ImageUploadPath); os.IsNotExist(err) {
// _ = os.Mkdir(ImageUploadPath, 0777)
//}
}
10 changes: 6 additions & 4 deletions common/rate-limit.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,19 @@ func (l *InMemoryRateLimiter) clearExpiredItems() {
}
}

func (l *InMemoryRateLimiter) Request(key string, maxRequestPerMinute int) bool {
// Request parameter duration's unit is seconds
func (l *InMemoryRateLimiter) Request(key string, maxRequestNum int, duration int64) bool {
l.mutex.Lock()
defer l.mutex.Unlock()
// [old <-- new]
queue, ok := l.store[key]
now := time.Now().Unix()
if ok {
if len(*queue) < maxRequestPerMinute {
if len(*queue) < maxRequestNum {
*queue = append(*queue, now)
return true
} else {
if now-(*queue)[0] >= 60 {
if now-(*queue)[0] >= duration {
*queue = (*queue)[1:]
*queue = append(*queue, now)
return true
Expand All @@ -60,7 +62,7 @@ func (l *InMemoryRateLimiter) Request(key string, maxRequestPerMinute int) bool
}
}
} else {
s := make([]int64, 0, maxRequestPerMinute)
s := make([]int64, 0, maxRequestNum)
l.store[key] = &s
*(l.store[key]) = append(*(l.store[key]), now)
}
Expand Down
9 changes: 9 additions & 0 deletions common/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package common

import "github.com/go-playground/validator/v10"

var Validate *validator.Validate

func init() {
Validate = validator.New()
}
43 changes: 21 additions & 22 deletions controller/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ type FileDeleteRequest struct {

func UploadFile(c *gin.Context) {
uploadPath := common.UploadPath
saveToDatabase := true
path := c.PostForm("path")
if path != "" { // Upload to explorer's path
uploadPath = filepath.Join(common.ExplorerRootPath, path)
if !strings.HasPrefix(uploadPath, common.ExplorerRootPath) {
// In this case the given path is not valid, so we reset it to ExplorerRootPath.
uploadPath = common.ExplorerRootPath
}
saveToDatabase = false
}
//saveToDatabase := true
//path := c.PostForm("path")
//if path != "" { // Upload to explorer's path
// uploadPath = filepath.Join(common.ExplorerRootPath, path)
// if !strings.HasPrefix(uploadPath, common.ExplorerRootPath) {
// // In this case the given path is not valid, so we reset it to ExplorerRootPath.
// uploadPath = common.ExplorerRootPath
// }
// saveToDatabase = false
//}

description := c.PostForm("description")
if description == "" {
Expand Down Expand Up @@ -68,18 +68,17 @@ func UploadFile(c *gin.Context) {
c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error()))
return
}
if saveToDatabase {
fileObj := &model.File{
Description: description,
Uploader: uploader,
Time: currentTime,
Link: link,
Filename: filename,
}
err = fileObj.Insert()
if err != nil {
_ = fmt.Errorf(err.Error())
}
// save to database
fileObj := &model.File{
Description: description,
Uploader: uploader,
Time: currentTime,
Link: link,
Filename: filename,
}
err = fileObj.Insert()
if err != nil {
_ = fmt.Errorf(err.Error())
}
}
c.Redirect(http.StatusSeeOther, "./")
Expand Down
11 changes: 9 additions & 2 deletions controller/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func GetNotice(c *gin.Context) {

func SendEmailVerification(c *gin.Context) {
email := c.Query("email")
if email == "" {
if err := common.Validate.Var(email, "required,email"); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "无效的参数",
Expand Down Expand Up @@ -74,13 +74,20 @@ func SendEmailVerification(c *gin.Context) {

func SendPasswordResetEmail(c *gin.Context) {
email := c.Query("email")
if email == "" || !model.IsEmailAlreadyTaken(email) {
if err := common.Validate.Var(email, "required,email"); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "无效的参数",
})
return
}
if !model.IsEmailAlreadyTaken(email) {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "该邮箱地址未注册",
})
return
}
code := common.GenerateVerificationCode(0)
common.RegisterVerificationCodeWithKey(email, code, common.PasswordResetPurpose)
link := fmt.Sprintf("%s/api/user/reset?email=%s&token=%s", common.ServerAddress, email, code)
Expand Down
8 changes: 8 additions & 0 deletions controller/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func setupLogin(user *model.User, c *gin.Context) {
return
}
user.Password = ""
user.Token = ""
c.JSON(http.StatusOK, gin.H{
"message": "",
"success": true,
Expand Down Expand Up @@ -115,6 +116,13 @@ func Register(c *gin.Context) {
})
return
}
if err := common.Validate.Struct(&user); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
if common.EmailVerificationEnabled {
if user.Email == "" || user.VerificationCode == "" {
c.JSON(http.StatusOK, gin.H{
Expand Down
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ go 1.16
require (
github.com/gin-contrib/sessions v0.0.5
github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19
github.com/gin-gonic/gin v1.7.4
github.com/gin-gonic/gin v1.8.1
github.com/go-playground/validator/v10 v10.11.1
github.com/go-redis/redis/v8 v8.11.5
github.com/google/uuid v1.3.0
github.com/jinzhu/gorm v1.9.12
golang.org/x/crypto v0.1.0 // indirect
github.com/stretchr/testify v1.8.0 // indirect
golang.org/x/crypto v0.1.0
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
)
Loading

0 comments on commit 76d1455

Please sign in to comment.