Skip to content

Commit 3575573

Browse files
committed
feat: check for server-only operations
1 parent 6231465 commit 3575573

File tree

9 files changed

+85
-4
lines changed

9 files changed

+85
-4
lines changed

common/router.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,12 @@ func (r *Router) Init() {
6565

6666
r.Router.Use(cors.New(cors.Config{
6767
AllowOrigins: utils.GlobalConfig.AllowedOrigins,
68-
AllowMethods: []string{"POST", "GET"},
68+
AllowMethods: []string{"POST", "GET", "PATCH", "DELETE"},
6969
AllowCredentials: true,
7070
MaxAge: time.Duration(utils.GlobalConfig.Token.Expiration) * time.Minute,
7171
}))
7272
r.Router.Use(middleware.TokenCheck)
73+
r.Router.Use(middleware.ServerCheck)
7374
}
7475

7576
func (r *Router) Run() {

errors/model.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const (
3030
RespErrMsgUnauth = "Authentication Failed"
3131

3232
RespErrCodeForbidden = 1202
33-
RespErrMsgForbidden = "No permission"
33+
RespErrMsgForbidden = "Forbidden"
3434

3535
RespErrCodeInvalidToken = 1203
3636
RespErrMsgInvalidToken = "Invalid token"

handlers/response.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package handlers
33
import (
44
"github.com/gin-gonic/gin"
55
"net/http"
6+
"seatimc/backend/errors"
67
)
78

89
type Response struct {
@@ -38,3 +39,13 @@ func RespTokenError(ctx *gin.Context, errCode int, errMsg string) {
3839
}
3940
ctx.JSON(resp.HttpCode, resp)
4041
}
42+
43+
func RespForbidden(ctx *gin.Context) {
44+
resp := Response{
45+
HttpCode: http.StatusForbidden,
46+
Code: errors.RespErrCodeForbidden,
47+
Msg: errors.RespErrMsgForbidden,
48+
Data: false,
49+
}
50+
ctx.JSON(resp.HttpCode, resp)
51+
}

handlers/user/verify-mcid.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"seatimc/backend/utils"
88
)
99

10-
func HandleVerifyMCID(ctx *gin.Context) *errors.CustomErr {
10+
func HandleMCIDVerify(ctx *gin.Context) *errors.CustomErr {
1111
playername := ctx.DefaultQuery("playername", "")
1212

1313
if playername == "" {

middleware/servercheck.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package middleware
2+
3+
import (
4+
"github.com/gin-gonic/gin"
5+
"seatimc/backend/handlers"
6+
"seatimc/backend/utils"
7+
)
8+
9+
func ServerCheck(ctx *gin.Context) {
10+
if !utils.IsServerOnly(ctx.Request.RequestURI) {
11+
return
12+
}
13+
14+
// Header naming conventions considered from https://stackoverflow.com/questions/3561381/custom-http-headers-naming-conventions
15+
if ctx.Request.Header.Get("Seati-Server-Secret") != utils.GlobalConfig.ServerSecret {
16+
handlers.RespForbidden(ctx)
17+
ctx.Abort()
18+
return
19+
}
20+
}

utils/booleans.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ func NeedAuthorize(uri string) bool {
1515
return false
1616
}
1717

18+
// 根据 URI 前缀判断该 URI 请求是否必须来自服务器
19+
func IsServerOnly(uri string) bool {
20+
needs := GlobalConfig.ServerOnlyEndpoints
21+
22+
for i := 0; i < len(needs); i++ {
23+
if strings.HasPrefix(uri, needs[i]) {
24+
return true
25+
}
26+
}
27+
28+
return false
29+
}
30+
1831
func IsTrue(boolean string) bool {
1932
return strings.EqualFold(boolean, "true")
2033
}

utils/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ type Config struct {
2828
Version string `yaml:"version"`
2929
EnableConfigWhitelist bool `yaml:"enable-config-whitelist"`
3030
NeedAuthorizeEndpoints []string `yaml:"need-authorize-endpoints"`
31+
ServerOnlyEndpoints []string `yaml:"server-only-endpoints"`
32+
ServerSecret string `yaml:"server-secret"`
3133
}
3234

3335
var GlobalConfig *Config

utils/database-user.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package utils
22

3-
import "seatimc/backend/errors"
3+
import (
4+
errs "errors"
5+
"gorm.io/gorm"
6+
"seatimc/backend/errors"
7+
)
48

59
func IsUsernameUsed(username string) (bool, *errors.CustomErr) {
610
conn := GetDBConn()
@@ -28,6 +32,30 @@ func IsMCIDUsed(mcid string) (bool, *errors.CustomErr) {
2832
return count > 0, nil
2933
}
3034

35+
func GetMCIDUsage(mcid string) (*MCIDUsage, *errors.CustomErr) {
36+
conn := GetDBConn()
37+
var user Users
38+
39+
result := conn.Model(&Users{}).Where(&Users{MCID: mcid}).First(&user)
40+
41+
if result.Error != nil {
42+
if errs.Is(result.Error, gorm.ErrRecordNotFound) {
43+
return &MCIDUsage{
44+
Used: false,
45+
Verified: false,
46+
With: "",
47+
}, nil
48+
}
49+
return nil, errors.DbError(result.Error)
50+
}
51+
52+
return &MCIDUsage{
53+
Used: true,
54+
Verified: user.MCIDVerified,
55+
With: user.Username,
56+
}, nil
57+
}
58+
3159
func GetUserByUsername(username string) (*Users, *errors.CustomErr) {
3260
conn := GetDBConn()
3361
var user Users

utils/structs.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ type JWTClaims struct {
1515
Payload JWTPayload `json:"payload"`
1616
}
1717

18+
type MCIDUsage struct {
19+
Used bool `json:"used"`
20+
Verified bool `json:"verified"`
21+
With string `json:"with"`
22+
}
23+
1824
/**
1925
* Status:
2026
* 1 - Pending - 创建中

0 commit comments

Comments
 (0)