Files
Kontrollverlust/main.go
T
irrlicht cb3da3bb24 Soft-Delete: Beiträge als [deleted] erhalten statt löschen
- entry.deleted; entrySelect LEFT JOIN + COALESCE(username)
- POST /entry/{pid}/delete: deleted=1, Inhalt/Bild/Autor geleert, Zeile bleibt
- Konto-Löschung soft-deletet die eigenen Beiträge (statt hartem DELETE),
  damit fremde Antworten nicht verwaisen
- Frontend: [deleted]-Platzhalter im Feed, Löschen-Button auf Focus-Seite
- notes/migrations.md: ALTER TABLE deleted

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 13:21:42 +02:00

77 lines
2.0 KiB
Go

package main
import (
"encoding/json"
"log"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
if err := initDB("kver.db"); err != nil {
log.Fatalf("db init: %v", err)
}
defer db.Close()
const addr = ":8080"
log.Printf("kver listening on %s", addr)
log.Fatal(http.ListenAndServe(addr, routes()))
}
// routes baut den HTTP-Handler mit allen Endpunkten. In main() und in den
// Tests identisch verwendet.
func routes() http.Handler {
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
// --- Auth (öffentlich) ---
r.Post("/auth/login", handleLogin)
r.Get("/auth/logout", handleLogout)
r.Post("/auth/newuser", handleNewUser)
r.Get("/auth/sessioninfo", handleSessionInfo)
r.Get("/auth/headerbar", handleHeaderbar)
// --- Entries ---
r.Get("/entry/feed/{page}", handleFeed)
r.Get("/entry/{pid}/votes", handleVotes)
r.Get("/entry/{pid}/thread", handleThread)
r.Get("/e/{pid}", serveEntryPage)
// --- User (öffentlich) ---
r.Get("/u/{username}", serveUserPage)
r.Get("/u/{username}/info", handleUserPage)
r.Get("/u/{username}/feed/{page}", handleUserFeed)
// --- Geschützt (Session erforderlich) ---
r.Group(func(r chi.Router) {
r.Use(requireAuth)
r.Post("/entry/create", handleCreateEntry)
r.Post("/entry/{pid}/vote", handleVote)
r.Post("/entry/{pid}/delete", handleDeleteEntry)
r.Get("/user/info", handleUserInfo)
r.Post("/user/rename", handleUserRename)
r.Post("/user/delete", handleUserDelete)
})
// Hochgeladene Medien + alte statische Assets
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
// Neues JS-Frontend
r.Handle("/*", http.FileServer(http.Dir("web")))
return r
}
func writeJSON(w http.ResponseWriter, status int, v any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
_ = json.NewEncoder(w).Encode(v)
}
func writeError(w http.ResponseWriter, status int, msg string) {
writeJSON(w, status, map[string]string{"error": msg})
}