feat: 重建 Bell GoAdmin 产品骨架 (#62)

This commit is contained in:
QiuSW
2026-08-27 18:20:40 +08:00
parent b37c350096
commit f5a3dd796b
715 changed files with 75278 additions and 0 deletions
@@ -0,0 +1,73 @@
package bellconfig
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
"github.com/go-admin-team/go-admin-core/sdk/config"
)
const (
DatabaseURLEnv = "BELL_DATABASE_URL"
JWTSecretEnv = "BELL_JWT_SECRET"
)
// Environment contains Bell's process-owned settings. It deliberately has no
// credentials or secret defaults so Sense and Bell cannot silently share them.
type Environment struct {
DatabaseURL string
JWTSecret string
Host string
Port int64
}
func Load(getenv func(string) string) (Environment, error) {
env := Environment{
DatabaseURL: strings.TrimSpace(getenv(DatabaseURLEnv)),
JWTSecret: strings.TrimSpace(getenv(JWTSecretEnv)),
Host: strings.TrimSpace(getenv("BELL_HOST")),
}
if env.DatabaseURL == "" {
return Environment{}, fmt.Errorf("%s is required", DatabaseURLEnv)
}
if env.JWTSecret == "" {
return Environment{}, fmt.Errorf("%s is required", JWTSecretEnv)
}
if len(env.JWTSecret) < 32 || env.JWTSecret == "go-admin" || strings.HasPrefix(env.JWTSecret, "__BELL_") {
return Environment{}, errors.New("BELL_JWT_SECRET must be a non-default value of at least 32 characters")
}
if env.Host == "" {
env.Host = "127.0.0.1"
}
if rawPort := strings.TrimSpace(getenv("BELL_PORT")); rawPort != "" {
port, err := strconv.ParseInt(rawPort, 10, 64)
if err != nil || port < 1 || port > 65535 {
return Environment{}, errors.New("BELL_PORT must be between 1 and 65535")
}
env.Port = port
}
return env, nil
}
func ApplyRequiredEnvironment() error {
env, err := Load(os.Getenv)
if err != nil {
return err
}
config.ApplicationConfig.Name = "bell"
config.ApplicationConfig.Host = env.Host
if env.Port != 0 {
config.ApplicationConfig.Port = env.Port
}
config.JwtConfig.Secret = env.JWTSecret
config.DatabaseConfig.Driver = "postgres"
config.DatabaseConfig.Source = env.DatabaseURL
for _, database := range config.DatabasesConfig {
database.Driver = "postgres"
database.Source = env.DatabaseURL
}
return nil
}
@@ -0,0 +1,33 @@
package bellconfig
import "testing"
func TestLoadRequiresIndependentDatabaseAndSecret(t *testing.T) {
for _, values := range []map[string]string{
{},
{DatabaseURLEnv: "postgres://bell@localhost/bell"},
{DatabaseURLEnv: "postgres://bell@localhost/bell", JWTSecretEnv: "go-admin"},
{DatabaseURLEnv: "postgres://bell@localhost/bell", JWTSecretEnv: "too-short"},
} {
_, err := Load(func(key string) string { return values[key] })
if err == nil {
t.Fatalf("Load(%v) unexpectedly succeeded", values)
}
}
}
func TestLoadAcceptsExactBellOverrides(t *testing.T) {
values := map[string]string{
DatabaseURLEnv: "postgres://bell@localhost/bell",
JWTSecretEnv: "bell-test-secret-with-at-least-32-characters",
"BELL_HOST": "127.0.0.2",
"BELL_PORT": "18091",
}
env, err := Load(func(key string) string { return values[key] })
if err != nil {
t.Fatal(err)
}
if env.Host != "127.0.0.2" || env.Port != 18091 {
t.Fatalf("unexpected listen override: %#v", env)
}
}