feat(welcome): 站点外观 - 合并欢迎页开放开关与入口分包修复
# Conflicts: # docs/content/docs/progress/pending-test.mdx
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"infinite-canvas/backend/internal/model"
|
||||
"infinite-canvas/backend/internal/platform"
|
||||
"infinite-canvas/backend/internal/protocol"
|
||||
"infinite-canvas/backend/internal/repository"
|
||||
|
||||
@@ -19,6 +20,9 @@ func TestFeatureAvailabilityDefaultsToDisableFrontendModels(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !setting.WelcomeEnabled {
|
||||
t.Fatal("welcome should be enabled by default")
|
||||
}
|
||||
if setting.Configured || !setting.ShortDramaEnabled || !setting.TaskCenterEnabled || !setting.CreditsEnabled || !setting.CustomChannelsEnabled || setting.FrontendModelsEnabled || !setting.PluginCenterEnabled || !setting.SystemPluginsVisibleToUsers {
|
||||
t.Fatalf("FeatureAvailability() = %#v", setting)
|
||||
}
|
||||
@@ -38,6 +42,28 @@ func TestFeatureAvailabilityLegacySettingKeepsCustomChannelsEnabled(t *testing.T
|
||||
if setting.ShortDramaEnabled || !setting.CustomChannelsEnabled || setting.FrontendModelsEnabled || !setting.PluginCenterEnabled || !setting.SystemPluginsVisibleToUsers {
|
||||
t.Fatalf("FeatureAvailability() = %#v", setting)
|
||||
}
|
||||
if !setting.WelcomeEnabled {
|
||||
t.Fatal("existing settings without welcomeEnabled should keep welcome enabled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWelcomeAvailabilityCanBeDisabledAndReenabled(t *testing.T) {
|
||||
svc, _ := newFeatureAvailabilityTestService(t)
|
||||
actor := &model.User{ID: "admin-welcome", Role: model.UserRoleAdmin}
|
||||
for _, enabled := range []bool{false, true} {
|
||||
value := platform.DefaultFeatureAvailability()
|
||||
value.WelcomeEnabled = enabled
|
||||
if _, err := svc.UpdateFeatureAvailability(actor, value); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
setting, err := svc.FeatureAvailability()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if setting.WelcomeEnabled != enabled {
|
||||
t.Fatalf("welcomeEnabled = %v, want %v", setting.WelcomeEnabled, enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateFeatureAvailabilityPersistsAndAudits(t *testing.T) {
|
||||
|
||||
@@ -9,6 +9,16 @@ import (
|
||||
)
|
||||
|
||||
func RegisterFeatureAvailabilityRoutes(r *gin.RouterGroup, svc *service.Service) {
|
||||
r.GET("/public/welcome", func(c *gin.Context) {
|
||||
c.Header("Cache-Control", "no-store")
|
||||
setting, err := svc.FeatureAvailability()
|
||||
if err != nil {
|
||||
failService(c, err)
|
||||
return
|
||||
}
|
||||
ok(c, gin.H{"welcomeEnabled": setting.WelcomeEnabled})
|
||||
})
|
||||
|
||||
r.GET("/features", func(c *gin.Context) {
|
||||
if _, err := currentUser(c, svc); err != nil {
|
||||
failService(c, err)
|
||||
|
||||
@@ -24,6 +24,16 @@ tags:
|
||||
- name: agent
|
||||
- name: admin
|
||||
paths:
|
||||
/public/welcome:
|
||||
get:
|
||||
tags: [meta]
|
||||
security: []
|
||||
summary: 读取欢迎页开放状态
|
||||
responses:
|
||||
"200":
|
||||
description: 信封 data 仅包含 welcomeEnabled 布尔值,默认 true;Cache-Control 为 no-store
|
||||
"500":
|
||||
description: 配置读取失败
|
||||
/agent/capabilities:
|
||||
get:
|
||||
tags: [agent]
|
||||
|
||||
56
backend/internal/handler/welcome_routes_test.go
Normal file
56
backend/internal/handler/welcome_routes_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"infinite-canvas/backend/internal/model"
|
||||
"infinite-canvas/backend/internal/repository"
|
||||
"infinite-canvas/backend/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestWelcomeAvailabilityPublicRoute(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sqlDB.SetMaxOpenConns(1)
|
||||
t.Cleanup(func() { _ = sqlDB.Close() })
|
||||
if err := db.AutoMigrate(&model.SystemSetting{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
router := gin.New()
|
||||
RegisterFeatureAvailabilityRoutes(router.Group("/api"), service.New(repository.New(db), t.TempDir()))
|
||||
for _, enabled := range []bool{true, false, true} {
|
||||
payload, _ := json.Marshal(map[string]bool{"welcomeEnabled": enabled})
|
||||
if err := db.Save(&model.SystemSetting{Key: "feature_availability", ValueJSON: string(payload)}).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
response := httptest.NewRecorder()
|
||||
router.ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/api/public/welcome", nil))
|
||||
if response.Code != http.StatusOK || response.Header().Get("Cache-Control") != "no-store" {
|
||||
t.Fatalf("unexpected public response: %d %s", response.Code, response.Body.String())
|
||||
}
|
||||
var body struct {
|
||||
Code int `json:"code"`
|
||||
Data map[string]bool `json:"data"`
|
||||
}
|
||||
if err := json.Unmarshal(response.Body.Bytes(), &body); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if body.Code != 0 || len(body.Data) != 1 || body.Data["welcomeEnabled"] != enabled {
|
||||
t.Fatalf("unexpected public payload: %s", response.Body.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ const (
|
||||
)
|
||||
|
||||
type FeatureAvailability struct {
|
||||
WelcomeEnabled bool `json:"welcomeEnabled"`
|
||||
ShortDramaEnabled bool `json:"shortDramaEnabled"`
|
||||
TaskCenterEnabled bool `json:"taskCenterEnabled"`
|
||||
CreditsEnabled bool `json:"creditsEnabled"`
|
||||
@@ -46,6 +47,7 @@ type PublicFeatureAvailability struct {
|
||||
func DefaultFeatureAvailability() FeatureAvailability {
|
||||
// 缺少配置代表尚未由运维接管;前台模型需要明确配置后才开放。
|
||||
return FeatureAvailability{
|
||||
WelcomeEnabled: true,
|
||||
ShortDramaEnabled: true,
|
||||
TaskCenterEnabled: true,
|
||||
CreditsEnabled: true,
|
||||
|
||||
Reference in New Issue
Block a user