Files
Andriy Oblivantsev e00280b653
CI / test (push) Successful in 3s
Merge branch 'feature/assets-s3-sharing'
Integrate asset metadata/storage support, TypeScript client asset APIs, docs updates, and the Leaflet demo while resolving conflicts with recent challenge IP/login persistence changes on main.

Made-with: Cursor
2026-03-02 21:23:31 +00:00

117 lines
2.7 KiB
Go

package main
import (
"log"
"net/http"
"os"
"strconv"
"strings"
"time"
"momswap/backend/internal/app"
httpapi "momswap/backend/internal/http"
"momswap/backend/internal/storage"
"momswap/backend/internal/store"
)
func main() {
addr := getEnv("ADDR", ":8122")
adminPublicKey := os.Getenv("ADMIN_PUBLIC_KEY")
servicePublicKey := getEnv("SERVICE_PUBLIC_KEY", adminPublicKey)
if adminPublicKey == "" {
adminPublicKey = readKeyFile(getEnv("ADMIN_PUBLIC_KEY_FILE", "etc/server-service.pub"))
}
if servicePublicKey == "" {
servicePublicKey = readKeyFile(getEnv("SERVICE_PUBLIC_KEY_FILE", "etc/server-service.pub"))
}
if servicePublicKey == "" {
servicePublicKey = adminPublicKey
}
var st store.Store
if databaseURL := os.Getenv("DATABASE_URL"); databaseURL != "" {
if err := store.Migrate(databaseURL); err != nil {
log.Fatalf("migrate: %v", err)
}
pg, err := store.NewPostgresStore(databaseURL)
if err != nil {
log.Fatalf("postgres: %v", err)
}
defer pg.Close()
st = pg
} else {
st = store.NewMemoryStore()
}
service := app.NewService(st, app.Config{
ChallengeTTL: 5 * time.Minute,
SessionTTL: 24 * time.Hour,
}, servicePublicKey)
service.BootstrapAdmin(adminPublicKey)
if signer, err := newAssetSignerFromEnv(); err != nil {
log.Printf("asset storage disabled: %v", err)
} else if signer != nil {
service.ConfigureAssetStorage(signer)
}
api := httpapi.NewAPI(service)
h := api.Routes()
if logDir := getEnv("LOG_DIR", "var/logs"); logDir != "" {
if wrapped, err := httpapi.WithRequestLogging(logDir, h); err != nil {
log.Printf("request logging disabled: %v", err)
} else {
h = wrapped
}
}
log.Printf("listening on %s", addr)
if err := http.ListenAndServe(addr, h); err != nil {
log.Fatalf("listen: %v", err)
}
}
func newAssetSignerFromEnv() (app.AssetURLSigner, error) {
endpoint := os.Getenv("S3_ENDPOINT")
bucket := os.Getenv("S3_BUCKET")
if endpoint == "" || bucket == "" {
return nil, nil
}
useTLS, err := strconv.ParseBool(getEnv("S3_USE_TLS", "false"))
if err != nil {
return nil, err
}
usePathStyle, err := strconv.ParseBool(getEnv("S3_USE_PATH_STYLE", "true"))
if err != nil {
return nil, err
}
signer, err := storage.NewS3Signer(storage.S3Config{
Endpoint: endpoint,
Region: getEnv("S3_REGION", "us-east-1"),
Bucket: bucket,
AccessKey: getEnv("S3_ACCESS_KEY", ""),
SecretKey: getEnv("S3_SECRET_KEY", ""),
UseTLS: useTLS,
PathStyle: usePathStyle,
})
if err != nil {
return nil, err
}
return signer, nil
}
func getEnv(key, fallback string) string {
v := os.Getenv(key)
if v == "" {
return fallback
}
return v
}
func readKeyFile(path string) string {
b, err := os.ReadFile(path)
if err != nil {
return ""
}
return strings.TrimSpace(string(b))
}