initial upload

This commit is contained in:
David Schroeder
2026-07-25 13:11:37 -05:00
commit 943ddb064f
25 changed files with 2586 additions and 0 deletions
+133
View File
@@ -0,0 +1,133 @@
package app
import (
"fmt"
"net/url"
"os"
"strconv"
"strings"
"time"
)
type Config struct {
ListenAddr string
PublicURL *url.URL
DatabaseDSN string
GiteaURL *url.URL
GiteaClientID string
GiteaClientSecret string
GiteaPackageOwner string
GiteaPackageUser string
GiteaPackageToken string
AllowedGiteaUsers map[string]struct{}
CookieSecret []byte
DefaultDuration time.Duration
DefaultHostLimit int
MaxHostLimit int
TrustProxyHeaders bool
}
func LoadConfig() (Config, error) {
var cfg Config
var err error
cfg.ListenAddr = envDefault("TAPM_LISTEN_ADDR", ":8080")
cfg.DatabaseDSN = os.Getenv("TAPM_DATABASE_DSN")
cfg.GiteaClientID = os.Getenv("TAPM_GITEA_CLIENT_ID")
cfg.GiteaClientSecret = os.Getenv("TAPM_GITEA_CLIENT_SECRET")
cfg.GiteaPackageOwner = envDefault("TAPM_GITEA_PACKAGE_OWNER", "TAI")
cfg.GiteaPackageUser = os.Getenv("TAPM_GITEA_PACKAGE_USERNAME")
cfg.GiteaPackageToken = os.Getenv("TAPM_GITEA_PACKAGE_TOKEN")
cfg.CookieSecret = []byte(os.Getenv("TAPM_COOKIE_SECRET"))
cfg.PublicURL, err = parseAbsoluteURL("TAPM_PUBLIC_URL")
if err != nil {
return cfg, err
}
cfg.GiteaURL, err = parseAbsoluteURL("TAPM_GITEA_URL")
if err != nil {
return cfg, err
}
cfg.DefaultDuration, err = time.ParseDuration(
envDefault("TAPM_DEFAULT_DURATION", "3h"),
)
if err != nil || cfg.DefaultDuration <= 0 {
return cfg, fmt.Errorf("TAPM_DEFAULT_DURATION must be positive")
}
cfg.DefaultHostLimit, err = envInt("TAPM_DEFAULT_HOST_LIMIT", 3)
if err != nil {
return cfg, err
}
cfg.MaxHostLimit, err = envInt("TAPM_MAX_HOST_LIMIT", 25)
if err != nil {
return cfg, err
}
if cfg.DefaultHostLimit < 1 || cfg.MaxHostLimit < cfg.DefaultHostLimit {
return cfg, fmt.Errorf("invalid default or maximum host limit")
}
cfg.TrustProxyHeaders, err = strconv.ParseBool(
envDefault("TAPM_TRUST_PROXY_HEADERS", "false"),
)
if err != nil {
return cfg, fmt.Errorf("TAPM_TRUST_PROXY_HEADERS: %w", err)
}
cfg.AllowedGiteaUsers = make(map[string]struct{})
for _, user := range strings.Split(
envDefault("TAPM_ALLOWED_GITEA_USERS", "taiadmin"),
",",
) {
user = strings.ToLower(strings.TrimSpace(user))
if user != "" {
cfg.AllowedGiteaUsers[user] = struct{}{}
}
}
required := map[string]string{
"TAPM_DATABASE_DSN": cfg.DatabaseDSN,
"TAPM_GITEA_CLIENT_ID": cfg.GiteaClientID,
"TAPM_GITEA_CLIENT_SECRET": cfg.GiteaClientSecret,
"TAPM_GITEA_PACKAGE_USERNAME": cfg.GiteaPackageUser,
"TAPM_GITEA_PACKAGE_TOKEN": cfg.GiteaPackageToken,
}
for name, value := range required {
if strings.TrimSpace(value) == "" {
return cfg, fmt.Errorf("%s is required", name)
}
}
if len(cfg.CookieSecret) < 32 {
return cfg, fmt.Errorf("TAPM_COOKIE_SECRET must contain at least 32 bytes")
}
if len(cfg.AllowedGiteaUsers) == 0 {
return cfg, fmt.Errorf("at least one Gitea user must be allowed")
}
return cfg, nil
}
func parseAbsoluteURL(name string) (*url.URL, error) {
raw := os.Getenv(name)
parsed, err := url.Parse(raw)
if err != nil || parsed.Scheme != "https" || parsed.Host == "" {
return nil, fmt.Errorf("%s must be an absolute HTTPS URL", name)
}
return parsed, nil
}
func envDefault(name, fallback string) string {
if value := os.Getenv(name); value != "" {
return value
}
return fallback
}
func envInt(name string, fallback int) (int, error) {
raw := envDefault(name, strconv.Itoa(fallback))
value, err := strconv.Atoi(raw)
if err != nil {
return 0, fmt.Errorf("%s must be an integer", name)
}
return value, nil
}