- 数据库默认文件 filecodebox.db → fileshare.db(config.go 默认值与全部文档/编排同步)
- Go module filecodebox → fileshare(全部 import 同步,build/vet/test 全绿)
- 应用版本 APP_VERSION 2.5.6 → 26.9(health 接口已验证返回 26.9)
- deploy 编排统一:compose 项目名、Postgres 默认凭据、minio 桶名、env 注释
- JWT issuer、存储临时目录前缀、web 包名同步 fileshare
- CI:镜像 tag 以 APP_VERSION 为唯一版本源,main/tag 推送即发布
${VER} + latest;tag 触发时校验 tag 名与 APP_VERSION 一致,防错版
- 本地开发库文件已改名 fileshare.db(含 -shm/-wal 清理)
84 lines
2.3 KiB
Go
84 lines
2.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"fileshare/internal/response"
|
|
)
|
|
|
|
const testSecret = "unit-test-secret-0123456789abcdef"
|
|
|
|
func init() { gin.SetMode(gin.TestMode) }
|
|
|
|
func TestSignAndVerifyAdminToken(t *testing.T) {
|
|
token, expiresAt, err := SignAdminToken(testSecret, time.Hour)
|
|
if err != nil {
|
|
t.Fatalf("签发失败: %v", err)
|
|
}
|
|
if expiresAt.Before(time.Now()) {
|
|
t.Fatal("过期时间不合理")
|
|
}
|
|
claims, err := VerifyAdminToken(testSecret, token)
|
|
if err != nil {
|
|
t.Fatalf("校验失败: %v", err)
|
|
}
|
|
if !claims.IsAdmin {
|
|
t.Fatal("is_admin 应为 true")
|
|
}
|
|
}
|
|
|
|
func TestVerifyTamperedToken(t *testing.T) {
|
|
token, _, _ := SignAdminToken(testSecret, time.Hour)
|
|
claims, err := VerifyAdminToken(testSecret+"-wrong", token)
|
|
if err == nil || claims != nil {
|
|
t.Fatal("密钥不匹配应校验失败")
|
|
}
|
|
// 篡改 payload
|
|
tampered := token[:len(token)-3] + "abc"
|
|
if _, err := VerifyAdminToken(testSecret, tampered); err == nil {
|
|
t.Fatal("篡改的 token 应校验失败")
|
|
}
|
|
// 非 HMAC 算法拒绝
|
|
algNone := "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc19hZG1pbiI6dHJ1ZX0."
|
|
if _, err := VerifyAdminToken(testSecret, algNone); err == nil {
|
|
t.Fatal("none 算法应被拒绝")
|
|
}
|
|
}
|
|
|
|
func TestAdminAuthMiddleware(t *testing.T) {
|
|
r := gin.New()
|
|
r.GET("/protected", AdminAuth(func() string { return testSecret }), func(c *gin.Context) {
|
|
response.OK(c, gin.H{"ok": true})
|
|
})
|
|
|
|
// 无 token → 401
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, httptest.NewRequest("GET", "/protected", nil))
|
|
if w.Code != http.StatusUnauthorized {
|
|
t.Fatalf("无 token 应 401: %d", w.Code)
|
|
}
|
|
// 有效 token → 200
|
|
token, _, _ := SignAdminToken(testSecret, time.Hour)
|
|
w = httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/protected", nil)
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("有效 token 应 200: %d %s", w.Code, w.Body.String())
|
|
}
|
|
// 过期 token → 401
|
|
expired, _, _ := SignAdminToken(testSecret, -time.Minute)
|
|
w = httptest.NewRecorder()
|
|
req = httptest.NewRequest("GET", "/protected", nil)
|
|
req.Header.Set("Authorization", "Bearer "+expired)
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusUnauthorized {
|
|
t.Fatalf("过期 token 应 401: %d", w.Code)
|
|
}
|
|
}
|