77 lines
2.7 KiB
Go
77 lines
2.7 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.pcux.cn/xuans/Smail/config"
|
|
"git.pcux.cn/xuans/Smail/services/access"
|
|
appcontext "git.pcux.cn/xuans/Smail/utils/context"
|
|
)
|
|
|
|
func TestConfigBackupReadDoesNotRequireRecentAuth(t *testing.T) {
|
|
root := t.TempDir()
|
|
if err := os.MkdirAll(filepath.Join(root, "config"), 0700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
legacy := []byte(`{"domain":"mail.example.com","webDomain":"mail.example.com","dbType":"sqlite","dbDSN":"./config/test.db","isInit":true,"httpPort":80,"httpsPort":443,"httpsEnabled":1}`)
|
|
if err := os.WriteFile(filepath.Join(root, "config", "config.json"), legacy, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
validation := config.RuntimeValidationOptions{HasSuperAdmin: true, Production: true}
|
|
if _, err := config.MigrateLegacyConfig(root, validation); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
manager, err := config.NewConfigManager(root, config.ConfigLoaderOptions{Validation: validation})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
previous := config.CurrentManager()
|
|
config.SetRuntimeManager(manager)
|
|
t.Cleanup(func() { config.SetRuntimeManager(previous) })
|
|
|
|
for _, role := range []access.Role{access.RoleSuperAdmin, access.RoleAdmin, access.RoleUser} {
|
|
t.Run(string(role), func(t *testing.T) {
|
|
ctx := &appcontext.Context{UserID: 1, Role: role, RecentAuth: false}
|
|
recorder := httptest.NewRecorder()
|
|
ListConfigBackups(ctx, recorder, httptest.NewRequest(http.MethodGet, "/api/v1/config/backups", nil))
|
|
if role != access.RoleSuperAdmin {
|
|
if recorder.Code != http.StatusForbidden {
|
|
t.Fatalf("非超级管理员不应读取配置备份:%d", recorder.Code)
|
|
}
|
|
return
|
|
}
|
|
var payload struct {
|
|
ErrorNo int `json:"errorNo"`
|
|
}
|
|
if err := json.Unmarshal(recorder.Body.Bytes(), &payload); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if recorder.Code != http.StatusOK || payload.ErrorNo != 0 {
|
|
t.Fatalf("超级管理员读取脱敏备份不应要求近期认证:%d", recorder.Code)
|
|
}
|
|
})
|
|
}
|
|
|
|
// 列表读取放宽不能改变实际回滚链路的近期认证要求。
|
|
for name, handler := range map[string]func(*appcontext.Context, http.ResponseWriter, *http.Request){
|
|
"preview": PreviewConfigRollback,
|
|
"ticket": IssueConfigRollbackTicket,
|
|
"execute": RollbackConfig,
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
recorder := httptest.NewRecorder()
|
|
handler(&appcontext.Context{UserID: 1, Role: access.RoleSuperAdmin}, recorder,
|
|
httptest.NewRequest(http.MethodPost, "/api/v1/config/rollback", strings.NewReader(`{"targetGeneration":1}`)))
|
|
if recorder.Code != http.StatusForbidden || !strings.Contains(recorder.Body.String(), "RECENT_AUTH_REQUIRED") {
|
|
t.Fatalf("回滚仍应要求近期认证:%d", recorder.Code)
|
|
}
|
|
})
|
|
}
|
|
}
|