You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

108 lines
2.8 KiB

package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"github.com/go-chi/chi/v5"
chimiddleware "github.com/go-chi/chi/v5/middleware"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/joho/godotenv"
"quake2dropzone/internal/auth"
"quake2dropzone/internal/files"
"quake2dropzone/internal/middleware"
)
func main() {
_ = godotenv.Load()
dsn := os.Getenv("DATABASE_URL")
if dsn == "" {
host := os.Getenv("DB_HOST")
if host == "" {
host = "localhost"
}
port := os.Getenv("DB_PORT")
if port == "" {
port = "15432"
}
name := os.Getenv("DB_NAME")
if name == "" {
name = "dropzone"
}
user := os.Getenv("DB_USER")
if user == "" {
user = "dropzone"
}
pass := os.Getenv("DB_PASSWORD")
dsn = fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", user, pass, host, port, name)
}
jwtSecret := os.Getenv("JWT_SECRET")
if jwtSecret == "" {
jwtSecret = "change-me-in-production"
}
diskRoot := os.Getenv("DISK_ROOT")
if diskRoot == "" {
diskRoot = "./diskroot"
}
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
db, err := pgxpool.New(context.Background(), dsn)
if err != nil {
log.Fatalf("failed to connect to database: %v", err)
}
defer db.Close()
if err := db.Ping(context.Background()); err != nil {
log.Fatalf("database ping failed: %v", err)
}
log.Println("connected to database")
r := chi.NewRouter()
r.Use(chimiddleware.Logger)
r.Use(chimiddleware.Recoverer)
r.Get("/api/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
// Public endpoints
r.Post("/api/auth/login", auth.NewLoginHandler(db, jwtSecret))
r.Get("/api/files/public", files.PublicListHandler(diskRoot))
r.Get("/api/files/public/*", files.PublicListHandler(diskRoot))
useXAccel := os.Getenv("NGINX_ACCEL") == "true"
r.Get("/api/files/download/public/*", files.PublicDownloadHandler(diskRoot, useXAccel))
r.Get("/api/files/raw/public/*", files.PublicRawHandler(diskRoot))
r.Get("/api/captcha", files.CaptchaHandler(jwtSecret))
r.Post("/api/files/zip/public", files.PublicZipHandler(diskRoot, jwtSecret))
// Protected endpoints (example)
r.Group(func(r chi.Router) {
r.Use(middleware.AuthRequired(jwtSecret))
r.Get("/api/me", func(w http.ResponseWriter, r *http.Request) {
claims := middleware.GetClaims(r)
fmt.Fprintf(w, `{"username":%q,"role":%q}`, claims.Username, claims.Role)
})
})
// Admin-only endpoints (example)
r.Group(func(r chi.Router) {
r.Use(middleware.AuthRequired(jwtSecret))
r.Use(middleware.AdminRequired)
r.Get("/api/admin/users", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"users":[]}`))
})
})
log.Printf("server listening on :%s", port)
if err := http.ListenAndServe(":"+port, r); err != nil {
log.Fatalf("server error: %v", err)
}
}