diff --git a/main.go b/main.go index 8953b25..056bee0 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,16 @@ package main import ( + "crypto/rand" + "encoding/hex" "encoding/json" "flag" "fmt" "log" "net/http" "os" + "sync" + "time" "github.com/joho/godotenv" ) @@ -37,7 +41,7 @@ func saveConfig(c *Config) error { func main() { - err := godotenv.Load() + err := godotenv.Load(".env") if err != nil { log.Fatal("Error loading .env file") } @@ -58,6 +62,10 @@ func main() { http.HandleFunc("GET /favicon.ico", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/icon.png") }) http.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/login.html") }) + http.HandleFunc("GET /admin", requireAuth(func(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, "./static/admin.html") + })) + http.HandleFunc("POST /newsletter/subscribe", func(w http.ResponseWriter, r *http.Request) { var req struct { Email string `json:"email"` @@ -101,6 +109,40 @@ func main() { } }) + http.HandleFunc("POST /login", func(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + password := r.Form.Get("password") + auth := r.Form.Get("totp") + + fmt.Println(os.Getenv("password"), os.Getenv("auth")) + if password == os.Getenv("password") && auth == os.Getenv("auth") { + fmt.Println("logged in") + token := generateSession() + + sessionMu.Lock() + sessionStore[token] = time.Now().Add(12 * time.Hour) + sessionMu.Unlock() + + http.SetCookie(w, &http.Cookie{ + Name: "session", + Value: token, + Path: "/", + HttpOnly: true, + Secure: true, + SameSite: http.SameSiteLaxMode, + Expires: time.Now().Add(12 * time.Hour), + }) + + // htmx reads this header and does the redirect client-side + w.Header().Set("HX-Redirect", "/admin") + w.WriteHeader(http.StatusOK) + } else { + // failure + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, `
`) + } + }) + //http.HandleFunc("/portfolio", Portfolio) http.HandleFunc("/git", func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "https://git.samantha42.xyz", http.StatusFound) @@ -111,3 +153,36 @@ func main() { log.Fatal(err) } } + +var sessionStore = map[string]time.Time{} +var sessionMu sync.RWMutex + +func generateSession() string { + b := make([]byte, 32) + rand.Read(b) + return hex.EncodeToString(b) +} + +func requireAuth(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie("session") + if err != nil { + http.Redirect(w, r, "/login", http.StatusSeeOther) + return + } + + sessionMu.RLock() + expiry, ok := sessionStore[cookie.Value] + sessionMu.RUnlock() + + if !ok || time.Now().After(expiry) { + sessionMu.Lock() + delete(sessionStore, cookie.Value) + sessionMu.Unlock() + http.Redirect(w, r, "/login", http.StatusSeeOther) + return + } + + next(w, r) + } +} diff --git a/site b/site index 1a709ad..89129da 100755 Binary files a/site and b/site differ diff --git a/static/admin.html b/static/admin.html new file mode 100644 index 0000000..dc2b4a7 --- /dev/null +++ b/static/admin.html @@ -0,0 +1,516 @@ + + + + + +