mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-08-30 04:37:06 +00:00
133 lines
4.0 KiB
Go
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>`))
|
|
}
|