mirror of https://github.com/rocboss/paopao-ce
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
6.9 KiB
223 lines
6.9 KiB
package settings
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/rocboss/paopao-ce/internal/conf"
|
|
"github.com/rocboss/paopao-ce/internal/model/web"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/schema"
|
|
)
|
|
|
|
func TestGetProfileUsesBootstrapDefaultsWhenNoOverride(t *testing.T) {
|
|
svc := newTestService(t)
|
|
|
|
profile, err := svc.GetProfile(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("GetProfile() error = %v", err)
|
|
}
|
|
if !profile.AllowUserRegister {
|
|
t.Fatalf("AllowUserRegister = false, want bootstrap true")
|
|
}
|
|
if profile.DefaultTweetVisibility != "friend" {
|
|
t.Fatalf("DefaultTweetVisibility = %q, want friend", profile.DefaultTweetVisibility)
|
|
}
|
|
if profile.CopyrightRight != "fallback-right" {
|
|
t.Fatalf("CopyrightRight = %q, want fallback-right", profile.CopyrightRight)
|
|
}
|
|
}
|
|
|
|
func TestUpdateEditableProfilePersistsOnlyEditableKeys(t *testing.T) {
|
|
svc := newTestService(t)
|
|
|
|
profile, err := svc.UpdateEditableProfile(context.Background(), EditableProfile{
|
|
UseFriendship: false,
|
|
EnableTrendsBar: true,
|
|
EnableWallet: true,
|
|
AllowTweetAttachment: false,
|
|
AllowTweetAttachmentPrice: false,
|
|
AllowTweetVideo: false,
|
|
DefaultTweetMaxLength: 1200,
|
|
TweetWebEllipsisSize: 300,
|
|
TweetMobileEllipsisSize: 200,
|
|
DefaultTweetVisibility: "public",
|
|
DefaultMsgLoopInterval: 3000,
|
|
CopyrightTop: "top",
|
|
CopyrightLeft: "left",
|
|
CopyrightLeftLink: "https://left.example.com",
|
|
CopyrightRight: "right",
|
|
CopyrightRightLink: "https://right.example.com",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("UpdateEditableProfile() error = %v", err)
|
|
}
|
|
if !profile.AllowUserRegister {
|
|
t.Fatalf("AllowUserRegister = false, want bootstrap true")
|
|
}
|
|
if !profile.AllowPhoneBind {
|
|
t.Fatalf("AllowPhoneBind = false, want bootstrap true")
|
|
}
|
|
if profile.DefaultTweetVisibility != "public" {
|
|
t.Fatalf("DefaultTweetVisibility = %q, want public", profile.DefaultTweetVisibility)
|
|
}
|
|
values, err := svc.GetValues(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("GetValues() error = %v", err)
|
|
}
|
|
if !hasValue(values.Items, "web_profile.enable_wallet", true, false) {
|
|
t.Fatalf("web_profile.enable_wallet override not found")
|
|
}
|
|
}
|
|
|
|
func TestSaveValuesEncryptsSecretsAtRest(t *testing.T) {
|
|
svc := newTestService(t)
|
|
conf.AdminSettingsSetting.EncryptionKey = "bootstrap-test-encryption-key"
|
|
svc.codec = newSecretCodec()
|
|
|
|
_, err := svc.SaveValues(context.Background(), []web.AdminSettingValueInput{{
|
|
Key: "meili.api_key",
|
|
Value: []byte(`"top-secret-key"`),
|
|
}})
|
|
if err != nil {
|
|
t.Fatalf("SaveValues() error = %v", err)
|
|
}
|
|
var record settingRecord
|
|
if err := svc.db.WithContext(context.Background()).First(&record, "key = ?", "meili.api_key").Error; err != nil {
|
|
t.Fatalf("load record error = %v", err)
|
|
}
|
|
if !record.IsEncrypted {
|
|
t.Fatalf("IsEncrypted = false, want true")
|
|
}
|
|
if strings.Contains(record.Value, "top-secret-key") {
|
|
t.Fatalf("record.Value stored plaintext = %q", record.Value)
|
|
}
|
|
}
|
|
|
|
func TestRestartRequiredValuesReportPendingRestart(t *testing.T) {
|
|
svc := newTestService(t)
|
|
|
|
resp, err := svc.SaveValues(context.Background(), []web.AdminSettingValueInput{{
|
|
Key: "meili.host",
|
|
Value: []byte(`"pending-restart:7700"`),
|
|
}})
|
|
if err != nil {
|
|
t.Fatalf("SaveValues() error = %v", err)
|
|
}
|
|
if !resp.HasPendingRestart {
|
|
t.Fatal("HasPendingRestart = false, want true")
|
|
}
|
|
if !hasValue(resp.Items, "meili.host", "pending-restart:7700", true) {
|
|
t.Fatalf("meili.host pending_restart not reported")
|
|
}
|
|
}
|
|
|
|
func TestSaveValuesRejectsInvalidSingleIntUpdate(t *testing.T) {
|
|
svc := newTestService(t)
|
|
|
|
_, err := svc.SaveValues(context.Background(), []web.AdminSettingValueInput{{
|
|
Key: "web_profile.default_tweet_max_length",
|
|
Value: []byte(`120`),
|
|
}})
|
|
if err == nil {
|
|
t.Fatal("SaveValues() error = nil, want invalid params error")
|
|
}
|
|
}
|
|
|
|
func TestSaveValuesAcceptsCoupledProfileUpdate(t *testing.T) {
|
|
svc := newTestService(t)
|
|
|
|
resp, err := svc.SaveValues(context.Background(), []web.AdminSettingValueInput{
|
|
{Key: "web_profile.default_tweet_max_length", Value: []byte(`120`)},
|
|
{Key: "web_profile.tweet_web_ellipsis_size", Value: []byte(`120`)},
|
|
{Key: "web_profile.tweet_mobile_ellipsis_size", Value: []byte(`120`)},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("SaveValues() error = %v", err)
|
|
}
|
|
if !hasValue(resp.Items, "web_profile.default_tweet_max_length", 120, false) {
|
|
t.Fatalf("web_profile.default_tweet_max_length override not found")
|
|
}
|
|
if conf.WebProfileSetting.DefaultTweetMaxLength != 120 {
|
|
t.Fatalf("DefaultTweetMaxLength = %d, want 120", conf.WebProfileSetting.DefaultTweetMaxLength)
|
|
}
|
|
}
|
|
|
|
func TestBootstrapAppliesPersistedOverrides(t *testing.T) {
|
|
svc := newTestService(t)
|
|
conf.AdminSettingsSetting.EncryptionKey = "bootstrap-test-encryption-key"
|
|
svc.codec = newSecretCodec()
|
|
|
|
_, err := svc.SaveValues(context.Background(), []web.AdminSettingValueInput{{
|
|
Key: "web_profile.enable_wallet",
|
|
Value: []byte(`true`),
|
|
}})
|
|
if err != nil {
|
|
t.Fatalf("SaveValues() error = %v", err)
|
|
}
|
|
conf.WebProfileSetting.EnableWallet = false
|
|
Bootstrap(context.Background(), svc.db)
|
|
if !conf.WebProfileSetting.EnableWallet {
|
|
t.Fatal("Bootstrap() did not apply persisted web_profile.enable_wallet override")
|
|
}
|
|
}
|
|
|
|
func newTestService(t *testing.T) *Service {
|
|
t.Helper()
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatalf("os.Getwd() error = %v", err)
|
|
}
|
|
root := filepath.Clean(filepath.Join(wd, "../../.."))
|
|
if err := os.Chdir(root); err != nil {
|
|
t.Fatalf("os.Chdir(%q) error = %v", root, err)
|
|
}
|
|
t.Cleanup(func() {
|
|
_ = os.Chdir(wd)
|
|
})
|
|
conf.Initial(nil, false)
|
|
conf.WebProfileSetting = &conf.WebProfileConf{
|
|
UseFriendship: true,
|
|
EnableTrendsBar: false,
|
|
EnableWallet: false,
|
|
AllowTweetAttachment: true,
|
|
AllowTweetAttachmentPrice: true,
|
|
AllowTweetVideo: true,
|
|
AllowUserRegister: true,
|
|
AllowPhoneBind: true,
|
|
DefaultTweetMaxLength: 2000,
|
|
TweetWebEllipsisSize: 400,
|
|
TweetMobileEllipsisSize: 300,
|
|
DefaultTweetVisibility: "friend",
|
|
DefaultMsgLoopInterval: 5000,
|
|
CopyrightTop: "fallback-top",
|
|
CopyrightLeft: "fallback-left",
|
|
CopyrightLeftLink: "",
|
|
CopyrightRight: "fallback-right",
|
|
CopyrightRightLink: "https://fallback.example.com",
|
|
}
|
|
bootstrapConfig = nil
|
|
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{NamingStrategy: schema.NamingStrategy{TablePrefix: "p_", SingularTable: true}})
|
|
if err != nil {
|
|
t.Fatalf("gorm.Open() error = %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&settingRecord{}); err != nil {
|
|
t.Fatalf("AutoMigrate() error = %v", err)
|
|
}
|
|
return NewService(db)
|
|
}
|
|
|
|
func hasValue(items []web.AdminSettingValue, key string, expected any, pending bool) bool {
|
|
for _, item := range items {
|
|
if item.Key != key {
|
|
continue
|
|
}
|
|
return item.Value == expected && item.PendingRestart == pending
|
|
}
|
|
return false
|
|
}
|