package middleware import ( "crypto/rand" "encoding/hex" "encoding/json" "net/http" "os" "sync" "time" ) const cookieName = "cf_session" var ( mu sync.RWMutex sessions = map[string]time.Time{} ) func newToken() string { b := make([]byte, 32) rand.Read(b) return hex.EncodeToString(b) } func validSession(token string) bool { mu.RLock() defer mu.RUnlock() exp, ok := sessions[token] return ok && time.Now().Before(exp) } func RequireAuth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie(cookieName) if err != nil || !validSession(cookie.Value) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusUnauthorized) json.NewEncoder(w).Encode(map[string]string{"error": "unauthorized"}) return } next.ServeHTTP(w, r) }) } func LoginHandler(w http.ResponseWriter, r *http.Request) { var body struct { Username string `json:"username"` Password string `json:"password"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]string{"error": "corpo inválido"}) return } wantUser := os.Getenv("APP_USERNAME") wantPass := os.Getenv("APP_PASSWORD") if wantUser == "" || body.Username != wantUser || body.Password != wantPass { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusUnauthorized) json.NewEncoder(w).Encode(map[string]string{"error": "credenciais inválidas"}) return } token := newToken() mu.Lock() sessions[token] = time.Now().Add(30 * 24 * time.Hour) mu.Unlock() http.SetCookie(w, &http.Cookie{ Name: cookieName, Value: token, Path: "/", HttpOnly: true, SameSite: http.SameSiteStrictMode, MaxAge: 30 * 24 * 60 * 60, }) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(map[string]string{"ok": "true"}) } func LogoutHandler(w http.ResponseWriter, r *http.Request) { if cookie, err := r.Cookie(cookieName); err == nil { mu.Lock() delete(sessions, cookie.Value) mu.Unlock() } http.SetCookie(w, &http.Cookie{ Name: cookieName, Value: "", Path: "/", MaxAge: -1, }) w.WriteHeader(http.StatusNoContent) } func MeHandler(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie(cookieName) if err != nil || !validSession(cookie.Value) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusUnauthorized) json.NewEncoder(w).Encode(map[string]string{"error": "unauthorized"}) return } w.WriteHeader(http.StatusNoContent) }