c129cb99fc
Single Go binary serving the API and an embedded keyboard-first UI for promoting fafflix titles into the cheeztv kids tree via hardlinks. - internal/library: hardlink sync, idempotent re-runs, drift reporting, strict single-path-element name validation as the traversal guard - internal/arr: minimal sonarr/radarr v3 client with a 60s list cache and a key-brokered poster proxy - internal/auth: server-side Authentik group enforcement on every route - internal/server: library JSON API, art proxy, health probes, SPA - ui: two-tile landing page, fuzzy-filtered title list, detail panel - Makefile, Dockerfile, .woodpecker pipelines, pre-commit config
88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package config
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseGroups(t *testing.T) {
|
|
cases := []struct {
|
|
in string
|
|
want []string
|
|
}{
|
|
{"", []string{}},
|
|
{"akP-mediamark-user", []string{"akP-mediamark-user"}},
|
|
{"a,b,c", []string{"a", "b", "c"}},
|
|
{" a , b ,, c ", []string{"a", "b", "c"}},
|
|
{"a b\tc", []string{"a", "b", "c"}},
|
|
{"a,\nb;c", []string{"a", "b", "c"}},
|
|
{",,,", []string{}},
|
|
}
|
|
for _, c := range cases {
|
|
if got := ParseGroups(c.in); !reflect.DeepEqual(got, c.want) {
|
|
t.Errorf("ParseGroups(%q) = %v, want %v", c.in, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadDefaults(t *testing.T) {
|
|
cfg, err := Load()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if cfg.Listen != ":8080" || cfg.MediaRoot != "/media" || cfg.KeysDir != "/etc/mediamark/keys" {
|
|
t.Fatalf("unexpected defaults: %+v", cfg)
|
|
}
|
|
if cfg.GroupsHeader != "X-Forwarded-Groups" {
|
|
t.Fatalf("GroupsHeader = %q", cfg.GroupsHeader)
|
|
}
|
|
if !reflect.DeepEqual(cfg.AllowedGroups, []string{"akP-mediamark-user"}) {
|
|
t.Fatalf("AllowedGroups = %v", cfg.AllowedGroups)
|
|
}
|
|
}
|
|
|
|
func TestLoadFailsClosed(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
env map[string]string
|
|
}{
|
|
{"blank allowed groups", map[string]string{"MEDIAMARK_ALLOWED_GROUPS": " , , "}},
|
|
{"relative media root", map[string]string{"MEDIAMARK_MEDIA_ROOT": "media"}},
|
|
{"non-http sonarr url", map[string]string{"MEDIAMARK_SONARR_URL": "sonarr:8989"}},
|
|
{"non-http radarr url", map[string]string{"MEDIAMARK_RADARR_URL": "ftp://radarr"}},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
for k, v := range c.env {
|
|
t.Setenv(k, v)
|
|
}
|
|
if _, err := Load(); err == nil {
|
|
t.Fatal("Load succeeded, want error")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoadOverrides(t *testing.T) {
|
|
t.Setenv("MEDIAMARK_LISTEN", ":9999")
|
|
t.Setenv("MEDIAMARK_MEDIA_ROOT", "/srv/media/")
|
|
t.Setenv("MEDIAMARK_ALLOWED_GROUPS", "akP-mediamark-user, akR-admins")
|
|
t.Setenv("MEDIAMARK_GROUPS_HEADER", "X-Auth-Request-Groups")
|
|
cfg, err := Load()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if cfg.Listen != ":9999" {
|
|
t.Errorf("Listen = %q", cfg.Listen)
|
|
}
|
|
if cfg.MediaRoot != "/srv/media" {
|
|
t.Errorf("MediaRoot = %q, want cleaned /srv/media", cfg.MediaRoot)
|
|
}
|
|
if !reflect.DeepEqual(cfg.AllowedGroups, []string{"akP-mediamark-user", "akR-admins"}) {
|
|
t.Errorf("AllowedGroups = %v", cfg.AllowedGroups)
|
|
}
|
|
if cfg.GroupsHeader != "X-Auth-Request-Groups" {
|
|
t.Errorf("GroupsHeader = %q", cfg.GroupsHeader)
|
|
}
|
|
}
|