Files
2025-11-24 22:49:17 -06:00

110 lines
3.1 KiB
Go

package handlers
import (
"html/template"
"log/slog"
"net/http"
"time"
"atcr.io/pkg/appview/middleware"
"atcr.io/pkg/appview/storage"
"atcr.io/pkg/atproto"
"atcr.io/pkg/auth/oauth"
)
// SettingsHandler handles the settings page
type SettingsHandler struct {
Templates *template.Template
Refresher *oauth.Refresher
RegistryURL string
}
func (h *SettingsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
user := middleware.GetUser(r)
if user == nil {
http.Redirect(w, r, "/auth/oauth/login?return_to=/settings", http.StatusFound)
return
}
// Create ATProto client with session provider (uses DoWithSession for DPoP nonce safety)
client := atproto.NewClientWithSessionProvider(user.PDSEndpoint, user.DID, h.Refresher)
// Fetch sailor profile
profile, err := storage.GetProfile(r.Context(), client)
if err != nil {
// Error fetching profile - log out user
slog.Warn("Failed to fetch profile, logging out", "component", "settings", "did", user.DID, "error", err)
http.Redirect(w, r, "/auth/logout", http.StatusFound)
return
}
if profile == nil {
// Profile doesn't exist yet (404) - user needs to log out and back in to create it
slog.Warn("Profile doesn't exist, logging out", "component", "settings", "did", user.DID)
http.Redirect(w, r, "/auth/logout", http.StatusFound)
return
}
slog.Debug("Fetched profile", "component", "settings", "did", user.DID, "default_hold", profile.DefaultHold)
data := struct {
PageData
Profile struct {
Handle string
DID string
PDSEndpoint string
DefaultHold string
}
}{
PageData: NewPageData(r, h.RegistryURL),
}
data.Profile.Handle = user.Handle
data.Profile.DID = user.DID
data.Profile.PDSEndpoint = user.PDSEndpoint
data.Profile.DefaultHold = profile.DefaultHold
if err := h.Templates.ExecuteTemplate(w, "settings", data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
// UpdateDefaultHoldHandler handles updating the default hold
type UpdateDefaultHoldHandler struct {
Refresher *oauth.Refresher
}
func (h *UpdateDefaultHoldHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
user := middleware.GetUser(r)
if user == nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
holdEndpoint := r.FormValue("hold_endpoint")
// Create ATProto client with session provider (uses DoWithSession for DPoP nonce safety)
client := atproto.NewClientWithSessionProvider(user.PDSEndpoint, user.DID, h.Refresher)
// Fetch existing profile or create new one
profile, err := storage.GetProfile(r.Context(), client)
if err != nil || profile == nil {
// Profile doesn't exist, create new one
profile = atproto.NewSailorProfileRecord(holdEndpoint)
} else {
// Update existing profile
profile.DefaultHold = holdEndpoint
profile.UpdatedAt = time.Now()
}
// Save profile
if err := storage.UpdateProfile(r.Context(), client, profile); err != nil {
http.Error(w, "Failed to update profile: "+err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/html")
w.Write([]byte(`<div class="success"><i data-lucide="check"></i> Default hold updated successfully!</div>`))
}