server: 平台抽象层+bilibili、服务端加密凭据库、角色中间件;web: 精简页面/路由、macOS 客户端(Swift)与多份方案文档;移除误入库的编译产物
This commit is contained in:
@@ -2,8 +2,6 @@ package api_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http/httptest"
|
||||
@@ -36,33 +34,33 @@ func TestMain(m *testing.M) {
|
||||
adm, err := gorm.Open(gormmysql.Open(adminDSN), &gorm.Config{})
|
||||
if err != nil {
|
||||
fmt.Println("skip: mysql admin connect failed:", err)
|
||||
os.Exit(0)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err = adm.Exec("CREATE DATABASE IF NOT EXISTS everypublish_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci").Error; err != nil {
|
||||
fmt.Println("skip: create test db failed:", err)
|
||||
os.Exit(0)
|
||||
os.Exit(1)
|
||||
}
|
||||
testDSN := "root:everypublish@tcp(127.0.0.1:3306)/everypublish_test?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
testDB, err = gorm.Open(gormmysql.Open(testDSN), &gorm.Config{})
|
||||
if err != nil {
|
||||
fmt.Println("skip: test db connect failed:", err)
|
||||
os.Exit(0)
|
||||
os.Exit(1)
|
||||
}
|
||||
resetTestDB()
|
||||
|
||||
cfg := &config.Config{
|
||||
ServerAddr: ":0",
|
||||
MySQLDSN: testDSN,
|
||||
RedisAddr: "127.0.0.1:6379",
|
||||
JWTSecret: "test-secret",
|
||||
BaseURL: "http://127.0.0.1:8090",
|
||||
StorageDir: "/tmp/everypublish-test",
|
||||
ServerAddr: ":0",
|
||||
MySQLDSN: testDSN,
|
||||
RedisAddr: "127.0.0.1:6379",
|
||||
JWTSecret: "test-secret",
|
||||
BaseURL: "http://127.0.0.1:8090",
|
||||
StorageDir: "/tmp/everypublish-test",
|
||||
ExecutorMode: "mock",
|
||||
}
|
||||
rds := cache.New(cfg)
|
||||
testHub = ws.NewHub()
|
||||
dsp := ws.NewDispatcher(testDB, testHub, cfg)
|
||||
_, serverKey, _ := ed25519.GenerateKey(rand.Reader)
|
||||
testRouter = api.Router(cfg, testDB, rds, testHub, serverKey, dsp)
|
||||
testRouter = api.Router(cfg, testDB, rds, testHub, dsp)
|
||||
code := m.Run()
|
||||
os.Exit(code)
|
||||
}
|
||||
@@ -73,8 +71,8 @@ func resetTestDB() {
|
||||
testHub.Clear()
|
||||
}
|
||||
for _, t := range []interface{}{
|
||||
&models.TransferToken{}, &models.PairingCode{}, &models.Notification{}, &models.AuditLog{},
|
||||
&models.Challenge{}, &models.AgentDevice{}, &models.Task{}, &models.Material{},
|
||||
&models.TransferToken{}, &models.Notification{}, &models.AuditLog{},
|
||||
&models.Challenge{}, &models.AgentDevice{}, &models.PairingCode{}, &models.TaskEvent{}, &models.Task{}, &models.Material{},
|
||||
&models.Account{}, &models.Member{}, &models.Workspace{}, &models.User{},
|
||||
} {
|
||||
testDB.Migrator().DropTable(t)
|
||||
@@ -174,6 +172,24 @@ func TestWorkspaceAndMemberFlow(t *testing.T) {
|
||||
if code != 200 || env.Code != 0 {
|
||||
t.Fatalf("create ws failed: %d %s", code, env.Message)
|
||||
}
|
||||
var secondWS models.Workspace
|
||||
_ = json.Unmarshal(env.Data, &secondWS)
|
||||
code, _ = doReq(t, "PUT", fmt.Sprintf("/api/v1/workspaces/%d", secondWS.ID), aAccess, gin.H{"name": "越权空间"})
|
||||
if code != 404 {
|
||||
t.Fatalf("cross-workspace update should be 404, got %d", code)
|
||||
}
|
||||
var ownWorkspaces struct {
|
||||
List []models.Workspace `json:"list"`
|
||||
}
|
||||
code, env = doReq(t, "GET", "/api/v1/workspaces", aAccess, nil)
|
||||
if code != 200 || env.Code != 0 {
|
||||
t.Fatalf("list own workspaces failed: %d %s", code, env.Message)
|
||||
}
|
||||
_ = json.Unmarshal(env.Data, &ownWorkspaces)
|
||||
if len(ownWorkspaces.List) == 0 {
|
||||
t.Fatal("owner should have at least one workspace")
|
||||
}
|
||||
primaryWSID := ownWorkspaces.List[0].ID
|
||||
// A 邀请 B(viewer)
|
||||
code, env = doReq(t, "POST", "/api/v1/members/invite", aAccess, gin.H{"email": "worker@test.com", "role": "viewer"})
|
||||
if code != 200 || env.Code != 0 {
|
||||
@@ -192,6 +208,17 @@ func TestWorkspaceAndMemberFlow(t *testing.T) {
|
||||
if code != 200 || env.Code != 0 {
|
||||
t.Fatalf("join failed: %d %s", code, env.Message)
|
||||
}
|
||||
code, env = doReq(t, "POST", fmt.Sprintf("/api/v1/auth/switch-workspace/%d", primaryWSID), bAccess, nil)
|
||||
if code != 200 || env.Code != 0 {
|
||||
t.Fatalf("workspace switch failed: %d %s", code, env.Message)
|
||||
}
|
||||
var switched tokens
|
||||
_ = json.Unmarshal(env.Data, &switched)
|
||||
bAccess = switched.AccessToken
|
||||
code, _ = doReq(t, "POST", "/api/v1/accounts", bAccess, gin.H{"platform": "douyin", "remark": "viewer-forbidden"})
|
||||
if code != 403 {
|
||||
t.Fatalf("viewer account write should be 403, got %d", code)
|
||||
}
|
||||
// A 查成员:2 人
|
||||
code, env = doReq(t, "GET", "/api/v1/members", aAccess, nil)
|
||||
if code != 200 || env.Code != 0 {
|
||||
@@ -219,6 +246,23 @@ func TestWorkspaceAndMemberFlow(t *testing.T) {
|
||||
if code != 200 || env.Code != 0 {
|
||||
t.Fatalf("update role failed: %d %s", code, env.Message)
|
||||
}
|
||||
code, env = doReq(t, "POST", fmt.Sprintf("/api/v1/auth/switch-workspace/%d", primaryWSID), bAccess, nil)
|
||||
if code != 200 || env.Code != 0 {
|
||||
t.Fatalf("workspace switch after role update failed: %d %s", code, env.Message)
|
||||
}
|
||||
_ = json.Unmarshal(env.Data, &switched)
|
||||
var switchInfo struct {
|
||||
MemberRole string `json:"memberRole"`
|
||||
}
|
||||
_ = json.Unmarshal(env.Data, &switchInfo)
|
||||
if switchInfo.MemberRole != "operator" {
|
||||
t.Fatalf("workspace switch should reflect updated role, got %q", switchInfo.MemberRole)
|
||||
}
|
||||
bAccess = switched.AccessToken
|
||||
code, env = doReq(t, "POST", "/api/v1/accounts", bAccess, gin.H{"platform": "douyin", "remark": "operator-allowed"})
|
||||
if code != 200 || env.Code != 0 {
|
||||
t.Fatalf("operator account write should be allowed: %d %s", code, env.Message)
|
||||
}
|
||||
// owner 不可被移除
|
||||
code, _ = doReq(t, "DELETE", fmt.Sprintf("/api/v1/members/%d", ownerMember), aAccess, nil)
|
||||
if code != 403 {
|
||||
@@ -240,8 +284,8 @@ func TestWorkspaceAndMemberFlow(t *testing.T) {
|
||||
t.Fatalf("audit list failed: %d %s", code, env.Message)
|
||||
}
|
||||
var al struct {
|
||||
List []models.AuditLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
List []models.AuditLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
_ = json.Unmarshal(env.Data, &al)
|
||||
if al.Total < 3 {
|
||||
|
||||
Reference in New Issue
Block a user