mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-08-31 13:17:09 +00:00
99 lines
2.5 KiB
Go
99 lines
2.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"database/sql"
|
|
"html/template"
|
|
"net/http"
|
|
|
|
"atcr.io/pkg/appview/db"
|
|
"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 {
|
|
DB *sql.DB
|
|
Templates *template.Template
|
|
RegistryURL string
|
|
}
|
|
|
|
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 {
|
|
http.Error(w, "User not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
// Look up user by DID
|
|
viewedUser, err := db.GetUserByDID(h.DB, 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.DB, did, resolvedHandle)
|
|
viewedUser.Handle = resolvedHandle
|
|
}
|
|
|
|
// Fetch repositories for this user
|
|
repos, err := db.GetUserRepositories(h.DB, viewedUser.DID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Convert to RepoCardData for template
|
|
cards := make([]db.RepoCardData, 0, len(repos))
|
|
for _, repo := range repos {
|
|
stats, err := db.GetRepositoryStats(h.DB, viewedUser.DID, repo.Name)
|
|
if err != nil {
|
|
// Continue with zero stats on error
|
|
stats = &db.RepositoryStats{
|
|
DID: viewedUser.DID,
|
|
Repository: repo.Name,
|
|
}
|
|
}
|
|
cards = append(cards, db.RepoCardData{
|
|
OwnerHandle: viewedUser.Handle,
|
|
Repository: repo.Name,
|
|
Title: repo.Title,
|
|
Description: repo.Description,
|
|
IconURL: repo.IconURL,
|
|
StarCount: stats.StarCount,
|
|
PullCount: stats.PullCount,
|
|
})
|
|
}
|
|
|
|
data := struct {
|
|
PageData
|
|
ViewedUser *db.User // User whose page we're viewing
|
|
Repositories []db.RepoCardData
|
|
HasProfile bool
|
|
}{
|
|
PageData: NewPageData(r, h.RegistryURL),
|
|
ViewedUser: viewedUser,
|
|
Repositories: cards,
|
|
HasProfile: hasProfile,
|
|
}
|
|
|
|
if err := h.Templates.ExecuteTemplate(w, "user", data); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|