703b2fafb0
Implement 12-factor configuration via environment variables and token-in-cookie authentication for Gitea API access. - internal/config/config.go: reads GITEA_URL, GITEA_TOKEN, LISTEN_ADDR, SESSION_SECRET from environment with validation - internal/auth/cookie.go: HMAC-signed HTTP-only cookie for storing Gitea API tokens (Secure, SameSite=Strict) - internal/middleware/auth.go: extracts token from cookie, injects into request context, redirects unauthenticated users to /settings - internal/middleware/logging.go: structured JSON request logging - internal/handlers/settings.go: settings page for entering/removing Gitea API token with mobile-first dark UI - cmd/server/main.go: integrated config, auth middleware, and settings Includes unit tests for config loading, cookie signing/verification, and auth middleware bypass/redirect logic. Closes leeworks-agents/gitea-mobile#2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
func TestLoad_Success(t *testing.T) {
|
|
os.Setenv("GITEA_URL", "https://gitea.example.com")
|
|
os.Setenv("SESSION_SECRET", "test-secret-that-is-at-least-32-chars-long")
|
|
os.Setenv("LISTEN_ADDR", ":9090")
|
|
os.Setenv("GITEA_TOKEN", "test-token")
|
|
defer func() {
|
|
os.Unsetenv("GITEA_URL")
|
|
os.Unsetenv("SESSION_SECRET")
|
|
os.Unsetenv("LISTEN_ADDR")
|
|
os.Unsetenv("GITEA_TOKEN")
|
|
}()
|
|
|
|
cfg, err := Load()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if cfg.GiteaURL != "https://gitea.example.com" {
|
|
t.Errorf("GiteaURL = %q, want %q", cfg.GiteaURL, "https://gitea.example.com")
|
|
}
|
|
if cfg.ListenAddr != ":9090" {
|
|
t.Errorf("ListenAddr = %q, want %q", cfg.ListenAddr, ":9090")
|
|
}
|
|
if cfg.GiteaToken != "test-token" {
|
|
t.Errorf("GiteaToken = %q, want %q", cfg.GiteaToken, "test-token")
|
|
}
|
|
}
|
|
|
|
func TestLoad_DefaultListenAddr(t *testing.T) {
|
|
os.Setenv("GITEA_URL", "https://gitea.example.com")
|
|
os.Setenv("SESSION_SECRET", "test-secret-that-is-at-least-32-chars-long")
|
|
os.Unsetenv("LISTEN_ADDR")
|
|
defer func() {
|
|
os.Unsetenv("GITEA_URL")
|
|
os.Unsetenv("SESSION_SECRET")
|
|
}()
|
|
|
|
cfg, err := Load()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if cfg.ListenAddr != ":8080" {
|
|
t.Errorf("ListenAddr = %q, want %q", cfg.ListenAddr, ":8080")
|
|
}
|
|
}
|
|
|
|
func TestLoad_MissingGiteaURL(t *testing.T) {
|
|
os.Unsetenv("GITEA_URL")
|
|
os.Setenv("SESSION_SECRET", "test-secret-that-is-at-least-32-chars-long")
|
|
defer os.Unsetenv("SESSION_SECRET")
|
|
|
|
_, err := Load()
|
|
if err == nil {
|
|
t.Fatal("expected error for missing GITEA_URL")
|
|
}
|
|
}
|
|
|
|
func TestLoad_MissingSessionSecret(t *testing.T) {
|
|
os.Setenv("GITEA_URL", "https://gitea.example.com")
|
|
os.Unsetenv("SESSION_SECRET")
|
|
defer os.Unsetenv("GITEA_URL")
|
|
|
|
_, err := Load()
|
|
if err == nil {
|
|
t.Fatal("expected error for missing SESSION_SECRET")
|
|
}
|
|
}
|
|
|
|
func TestLoad_ShortSessionSecret(t *testing.T) {
|
|
os.Setenv("GITEA_URL", "https://gitea.example.com")
|
|
os.Setenv("SESSION_SECRET", "tooshort")
|
|
defer func() {
|
|
os.Unsetenv("GITEA_URL")
|
|
os.Unsetenv("SESSION_SECRET")
|
|
}()
|
|
|
|
_, err := Load()
|
|
if err == nil {
|
|
t.Fatal("expected error for short SESSION_SECRET")
|
|
}
|
|
}
|