collinenlucy.nl/controller.go

206 lines
4.8 KiB
Go
Raw Normal View History

2025-06-30 12:37:33 +02:00
package main
import (
"database/sql"
2025-06-30 12:37:33 +02:00
"encoding/base64"
"encoding/json"
2025-06-30 12:37:33 +02:00
"fmt"
2025-06-30 12:37:33 +02:00
"log"
2025-06-30 12:37:33 +02:00
"net/http"
"os"
"strconv"
2025-06-30 12:37:33 +02:00
"strings"
2025-06-30 12:37:33 +02:00
"time"
)
2025-06-30 12:37:33 +02:00
var token string
2025-06-30 12:37:33 +02:00
type Handler struct {
db *sql.DB
ntfy *Ntfy
visits *VisitHandler
2025-06-30 12:37:33 +02:00
}
func getStaticFile(relPath string, contentType string, w http.ResponseWriter) {
file, err := os.ReadFile(relPath)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "%s", err.Error())
return
}
w.Header().Add("Content-Type", contentType)
w.WriteHeader(http.StatusOK)
w.Write(file)
}
func isAuthorized(r *http.Request) bool {
auth := r.Header.Get("Authorization")
if auth == "" {
return false
}
return auth == fmt.Sprintf("Basic %s", token)
}
func (h *Handler) getRsvps(w http.ResponseWriter, r *http.Request) {
if !isAuthorized(r) {
w.WriteHeader(http.StatusUnauthorized)
return
}
rsvps, err := GetRsvps(h.db)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "%s", err.Error())
return
}
marshalledRsvps, err := json.Marshal(rsvps)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "%s", err.Error())
return
}
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "%s", marshalledRsvps)
}
func (h *Handler) createRsvp(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusBadRequest)
return
}
attending := r.Form.Get("attending") == "true"
partySize, err := strconv.ParseInt(r.Form.Get("party-size"), 10, 64)
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusBadRequest)
return
}
partyMembers := make([]Member, partySize)
for i := range partySize {
name := r.Form.Get(fmt.Sprintf("name-%d", i))
child := r.Form.Has(fmt.Sprintf("child-%d", i)) && r.Form.Get(fmt.Sprintf("child-%d", i)) == "true"
dietaryPreferences := r.Form.Get(fmt.Sprintf("diet-%d", i))
member := Member{
Name: name,
Child: child,
DietaryPreferences: dietaryPreferences,
}
partyMembers[i] = member
}
rsvp := Rsvp{
Attending: attending,
PartySize: partySize,
PartyMembers: partyMembers,
}
_, err = rsvp.CreateRsvp(h.db)
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if h.ntfy != nil {
SendRsvpNotification(h.ntfy, &rsvp)
}
w.Header().Add("Location", "/rsvp_confirmed")
w.WriteHeader(http.StatusSeeOther)
}
2025-06-30 12:37:33 +02:00
func SetupAuth() {
var username string
var password string
for _, entry := range os.Environ() {
split := strings.Split(entry, "=")
switch split[0] {
case "USERNAME":
username = split[1]
case "PASSWORD":
password = split[1]
}
if username != "" && password != "" {
break
}
}
if username == "" || password == "" {
log.Fatal("no authorization details")
}
sb := new(strings.Builder)
encoder := base64.NewEncoder(base64.StdEncoding, sb)
encoder.Write(fmt.Appendf(nil, "%s:%s", username, password))
encoder.Close()
token = sb.String()
2025-06-30 12:37:33 +02:00
fmt.Println("auth ready")
2025-06-30 12:37:33 +02:00
}
2025-06-30 12:37:33 +02:00
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%s - [%s] (%s) %s\n", time.Now().Format(time.RFC3339), r.RemoteAddr, r.Method, r.URL)
h.visits.HandleVisit(r.RemoteAddr)
2025-06-30 12:37:33 +02:00
switch true {
2025-08-27 18:13:06 +02:00
case r.Method == "GET" && r.URL.Path == "/favicon.ico":
getStaticFile("./client/favicon.ico", "image/png", w)
2025-06-30 12:37:33 +02:00
case r.Method == "GET" && r.URL.Path == "/":
getStaticFile("./client/index.html", "text/html", w)
case r.Method == "GET" && r.URL.Path == "/rsvp":
getStaticFile("./client/rsvp.html", "text/html", w)
case r.Method == "GET" && r.URL.Path == "/rsvp_confirmed":
getStaticFile("./client/rsvp_confirmed.html", "text/html", w)
case r.Method == "GET" && r.URL.Path == "/rsvps_list":
getStaticFile("./client/rsvps_list.html", "text/html", w)
2025-07-10 09:35:25 +02:00
case r.Method == "GET" && r.URL.Path == "/login":
getStaticFile("./client/login.html", "text/html", w)
case r.Method == "GET" && r.URL.Path == "/index.js":
getStaticFile("./client/index.js", "text/javascript", w)
case r.Method == "GET" && r.URL.Path == "/rsvp.js":
getStaticFile("./client/rsvp.js", "text/javascript", w)
case r.Method == "GET" && r.URL.Path == "/rsvp_confirmed.js":
getStaticFile("./client/rsvp_confirmed.js", "text/javascript", w)
case r.Method == "GET" && r.URL.Path == "/rsvps_list.js":
getStaticFile("./client/rsvps_list.js", "text/javascript", w)
2025-07-10 09:35:25 +02:00
case r.Method == "GET" && r.URL.Path == "/login.js":
getStaticFile("./client/login.js", "text/javascript", w)
case r.Method == "GET" && r.URL.Path == "/style.css":
getStaticFile("./client/style.css", "text/css", w)
case r.Method == "GET" && r.URL.Path == "/api/rsvps":
h.getRsvps(w, r)
case r.Method == "POST" && r.URL.Path == "/api/rsvps":
h.createRsvp(w, r)
2025-06-30 12:37:33 +02:00
default:
w.WriteHeader(http.StatusNotFound)
}
}