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

95 lines
2.7 KiB
Go

package handlers
import (
"log"
"net/http"
"atcr.io/pkg/appview/db"
"atcr.io/pkg/appview/middleware"
"atcr.io/pkg/atproto"
"github.com/go-chi/chi/v5"
)
// UserPageHandler handles the public user page showing all images for a user
type UserPageHandler struct {
BaseUIHandler
}
func (h *UserPageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
identifier := chi.URLParam(r, "handle")
// Resolve identifier (handle or DID) to canonical DID and current handle
did, resolvedHandle, pdsEndpoint, err := atproto.ResolveIdentity(r.Context(), identifier)
if err != nil {
RenderNotFound(w, r, &h.BaseUIHandler)
return
}
// Look up user by DID
viewedUser, err := db.GetUserByDID(h.ReadOnlyDB, did)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
hasProfile := true
if viewedUser == nil {
// Valid ATProto user but hasn't set up ATCR profile
hasProfile = false
viewedUser = &db.User{
DID: did,
Handle: resolvedHandle,
PDSEndpoint: pdsEndpoint,
// Avatar intentionally empty - template shows '?' placeholder
}
} else if viewedUser.Handle != resolvedHandle {
// Opportunistically update cached handle if it changed
_ = db.UpdateUserHandle(h.ReadOnlyDB, did, resolvedHandle)
viewedUser.Handle = resolvedHandle
}
// Get current user DID for star state (empty string if not logged in)
var currentUserDID string
if user := middleware.GetUser(r); user != nil {
currentUserDID = user.DID
}
// Fetch repository cards for this user
cards, err := db.GetUserRepoCards(h.ReadOnlyDB, viewedUser.DID, currentUserDID)
if err != nil {
log.Printf("Error fetching repo cards for user %s: %v", viewedUser.DID, err)
cards = []db.RepoCardData{}
}
db.SetRegistryURL(cards, h.RegistryURL)
// Build page meta
meta := NewPageMeta(
viewedUser.Handle+" - "+h.ClientShortName,
"Container images by "+viewedUser.Handle+" on "+h.ClientShortName+", the decentralized container registry",
).
WithCanonical("https://" + h.SiteURL + "/u/" + viewedUser.Handle).
WithOGImage("https://" + h.SiteURL + "/og/u/" + viewedUser.Handle).
WithOGType("profile").
WithSiteName(h.ClientShortName).
WithJSONLD(NewJSONLDProfilePage(h.SiteURL, viewedUser.Handle, viewedUser.Avatar))
data := struct {
PageData
Meta *PageMeta
ViewedUser *db.User // User whose page we're viewing
Repositories []db.RepoCardData
HasProfile bool
}{
PageData: NewPageData(r, &h.BaseUIHandler),
Meta: meta,
ViewedUser: viewedUser,
Repositories: cards,
HasProfile: hasProfile,
}
if err := h.Templates.ExecuteTemplate(w, "user", data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}