Files
at-container-registry/pkg/appview/handlers/settings.go
T

133 lines
4.0 KiB
Go

package handlers
import (
"fmt"
"html/template"
"net/http"
"time"
"atcr.io/pkg/appview/middleware"
"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
}
// Get OAuth session for the user
session, err := h.Refresher.GetSession(r.Context(), user.DID)
if err != nil {
// OAuth session not found or expired - redirect to re-authenticate
fmt.Printf("WARNING [settings]: OAuth session not found for %s: %v - redirecting to login\n", user.DID, err)
http.Redirect(w, r, "/auth/oauth/login?return_to=/settings", http.StatusFound)
return
}
// Use indigo's API client directly - it handles all auth automatically
apiClient := session.APIClient()
// Create ATProto client with indigo's XRPC client
client := atproto.NewClientWithIndigoClient(user.PDSEndpoint, user.DID, apiClient)
// Fetch sailor profile
profile, err := atproto.GetProfile(r.Context(), client)
if err != nil {
// Error fetching profile - log out user
fmt.Printf("WARNING [settings]: Failed to fetch profile for %s: %v - logging out\n", user.DID, 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
fmt.Printf("WARNING [settings]: Profile doesn't exist for %s - logging out\n", user.DID)
http.Redirect(w, r, "/auth/logout", http.StatusFound)
return
}
fmt.Printf("DEBUG [settings]: Fetched profile for %s: defaultHold=%s\n", user.DID, 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")
// Get OAuth session for the user
session, err := h.Refresher.GetSession(r.Context(), user.DID)
if err != nil {
// OAuth session not found or expired - redirect to re-authenticate
fmt.Printf("WARNING [settings]: OAuth session not found for %s: %v - redirecting to login\n", user.DID, err)
http.Redirect(w, r, "/auth/oauth/login?return_to=/settings", http.StatusFound)
return
}
// Use indigo's API client directly - it handles all auth automatically
apiClient := session.APIClient()
// Create ATProto client with indigo's XRPC client
client := atproto.NewClientWithIndigoClient(user.PDSEndpoint, user.DID, apiClient)
// Fetch existing profile or create new one
profile, err := atproto.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 := atproto.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">✓ Default hold updated successfully!</div>`))
}