internal/api: better multi-sites support; validate events against allowed domains

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Iff1ced4966b4d42cfd6dfefb0cfd97696a6a6964
This commit is contained in:
raf 2026-03-01 14:27:20 +03:00
commit 18fe1a8234
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
10 changed files with 542 additions and 35 deletions

View file

@ -17,7 +17,7 @@ type Config struct {
// Site-specific settings
type SiteConfig struct {
Domain string `yaml:"domain"`
Domains []string `yaml:"domains"` // list of allowed domains
SaltRotation string `yaml:"salt_rotation"`
Collect CollectConfig `yaml:"collect"`
CustomEvents []string `yaml:"custom_events"`
@ -31,6 +31,7 @@ type CollectConfig struct {
Country bool `yaml:"country"`
Device bool `yaml:"device"`
Referrer string `yaml:"referrer"`
Domain bool `yaml:"domain"` // track domain as metric dimension (for multi-site)
}
// Path normalization options
@ -106,8 +107,8 @@ func Load(path string) (*Config, error) {
// Check required fields and sets defaults
func (c *Config) Validate() error {
// Site validation
if c.Site.Domain == "" {
return fmt.Errorf("site.domain is required")
if len(c.Site.Domains) == 0 {
return fmt.Errorf("site.domains is required")
}
// Validate salt_rotation

View file

@ -10,8 +10,8 @@ func TestLoadConfig_ValidFile(t *testing.T) {
t.Fatalf("expected no error, got %v", err)
}
if cfg.Site.Domain != "example.com" {
t.Errorf("expected domain 'example.com', got '%s'", cfg.Site.Domain)
if len(cfg.Site.Domains) == 0 || cfg.Site.Domains[0] != "example.com" {
t.Errorf("expected domains to contain 'example.com', got %v", cfg.Site.Domains)
}
if cfg.Site.SaltRotation != "daily" {
@ -29,7 +29,7 @@ func TestLoadConfig_MissingFile(t *testing.T) {
func TestValidate_MaxPathsRequired(t *testing.T) {
cfg := &Config{
Site: SiteConfig{
Domain: "example.com",
Domains: []string{"example.com"},
SaltRotation: "daily",
},
Limits: LimitsConfig{