mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-25 03:34:14 +00:00
clean up duplicate functions
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -37,7 +36,7 @@ func (h *StarRepositoryHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
||||
repository := chi.URLParam(r, "repository")
|
||||
|
||||
// Resolve owner's handle to DID
|
||||
ownerDID, err := resolveIdentityToDID(r.Context(), h.Directory, handle)
|
||||
ownerDID, err := atproto.ResolveHandleToDID(r.Context(), handle)
|
||||
if err != nil {
|
||||
slog.Warn("Failed to resolve handle for star", "handle", handle, "error", err)
|
||||
http.Error(w, fmt.Sprintf("Failed to resolve handle: %v", err), http.StatusBadRequest)
|
||||
@@ -95,7 +94,7 @@ func (h *UnstarRepositoryHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
||||
repository := chi.URLParam(r, "repository")
|
||||
|
||||
// Resolve owner's handle to DID
|
||||
ownerDID, err := resolveIdentityToDID(r.Context(), h.Directory, handle)
|
||||
ownerDID, err := atproto.ResolveHandleToDID(r.Context(), handle)
|
||||
if err != nil {
|
||||
slog.Warn("Failed to resolve handle for unstar", "handle", handle, "error", err)
|
||||
http.Error(w, fmt.Sprintf("Failed to resolve handle: %v", err), http.StatusBadRequest)
|
||||
@@ -156,7 +155,7 @@ func (h *CheckStarHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
repository := chi.URLParam(r, "repository")
|
||||
|
||||
// Resolve owner's handle to DID
|
||||
ownerDID, err := resolveIdentityToDID(r.Context(), h.Directory, handle)
|
||||
ownerDID, err := atproto.ResolveHandleToDID(r.Context(), handle)
|
||||
if err != nil {
|
||||
slog.Warn("Failed to resolve handle for check star", "handle", handle, "error", err)
|
||||
http.Error(w, fmt.Sprintf("Failed to resolve handle: %v", err), http.StatusBadRequest)
|
||||
@@ -200,7 +199,7 @@ func (h *GetStatsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
repository := chi.URLParam(r, "repository")
|
||||
|
||||
// Resolve owner's handle to DID
|
||||
ownerDID, err := resolveIdentityToDID(r.Context(), h.Directory, handle)
|
||||
ownerDID, err := atproto.ResolveHandleToDID(r.Context(), handle)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to resolve handle", http.StatusBadRequest)
|
||||
return
|
||||
@@ -231,7 +230,7 @@ func (h *ManifestDetailHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
||||
digest := chi.URLParam(r, "digest")
|
||||
|
||||
// Resolve owner's handle to DID
|
||||
ownerDID, err := resolveIdentityToDID(r.Context(), h.Directory, handle)
|
||||
ownerDID, err := atproto.ResolveHandleToDID(r.Context(), handle)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to resolve handle", http.StatusBadRequest)
|
||||
return
|
||||
@@ -253,9 +252,3 @@ func (h *ManifestDetailHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(manifest)
|
||||
}
|
||||
|
||||
// resolveIdentityToDID is a helper function that resolves a handle or DID to a DID
|
||||
func resolveIdentityToDID(ctx context.Context, directory identity.Directory, identityStr string) (string, error) {
|
||||
// Resolve to DID via directory (handles both handles and DIDs)
|
||||
return atproto.ResolveHandleToDID(ctx, identityStr)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"atcr.io/pkg/atproto"
|
||||
)
|
||||
|
||||
func TestNewChecker(t *testing.T) {
|
||||
@@ -317,7 +319,7 @@ func TestNormalizeHoldEndpoint(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := normalizeHoldEndpoint(tt.input)
|
||||
result := atproto.ResolveHoldDIDFromURL(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("normalizeHoldEndpoint(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"atcr.io/pkg/atproto"
|
||||
)
|
||||
|
||||
// DBQuerier interface for database queries (allows mocking in tests)
|
||||
@@ -129,7 +130,7 @@ func (w *Worker) refreshAllHolds(ctx context.Context) {
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
// Normalize to canonical DID format
|
||||
normalizedDID := normalizeHoldEndpoint(endpoint)
|
||||
normalizedDID := atproto.ResolveHoldDIDFromURL(endpoint)
|
||||
|
||||
// Skip if we've already seen this normalized DID
|
||||
if seen[normalizedDID] {
|
||||
@@ -219,29 +220,3 @@ func (a *DBAdapter) GetUniqueHoldEndpoints() ([]string, error) {
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
// normalizeHoldEndpoint converts a hold endpoint (URL or DID) to canonical DID format
|
||||
// This ensures that different representations of the same hold are deduplicated:
|
||||
// - http://172.28.0.3:8080 → did:web:172.28.0.3:8080
|
||||
// - http://hold01.atcr.io → did:web:hold01.atcr.io
|
||||
// - https://hold01.atcr.io → did:web:hold01.atcr.io
|
||||
// - did:web:hold01.atcr.io → did:web:hold01.atcr.io (passthrough)
|
||||
func normalizeHoldEndpoint(endpoint string) string {
|
||||
// Strip protocol and trailing slashes
|
||||
normalized := endpoint
|
||||
normalized = strings.TrimPrefix(normalized, "http://")
|
||||
normalized = strings.TrimPrefix(normalized, "https://")
|
||||
normalized = strings.TrimSuffix(normalized, "/")
|
||||
|
||||
// If already a DID, return as-is
|
||||
if strings.HasPrefix(endpoint, "did:") {
|
||||
return endpoint
|
||||
}
|
||||
|
||||
// Extract hostname (remove path if present)
|
||||
parts := strings.Split(normalized, "/")
|
||||
hostname := parts[0]
|
||||
|
||||
// Convert to did:web
|
||||
return "did:web:" + hostname
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ type Processor struct {
|
||||
// useCache: true for Worker (live streaming), false for Backfill (batch processing)
|
||||
func NewProcessor(database *sql.DB, useCache bool) *Processor {
|
||||
p := &Processor{
|
||||
db: database,
|
||||
useCache: useCache,
|
||||
db: database,
|
||||
useCache: useCache,
|
||||
}
|
||||
|
||||
if useCache {
|
||||
|
||||
@@ -525,7 +525,6 @@ func TestTemplates(t *testing.T) {
|
||||
|
||||
// Test that all expected templates are loaded
|
||||
expectedTemplates := []string{
|
||||
"base.html",
|
||||
"nav",
|
||||
"repo-card",
|
||||
"repository",
|
||||
|
||||
@@ -406,8 +406,11 @@ func ParseStarRecordKey(rkey string) (ownerDID, repository string, err error) {
|
||||
}
|
||||
|
||||
// ResolveHoldDIDFromURL converts a hold endpoint URL to a did:web DID
|
||||
// For did:web holds: https://hold01.atcr.io → did:web:hold01.atcr.io
|
||||
// If input is already a DID, returns it as-is
|
||||
// This ensures that different representations of the same hold are deduplicated:
|
||||
// - http://172.28.0.3:8080 → did:web:172.28.0.3:8080
|
||||
// - http://hold01.atcr.io → did:web:hold01.atcr.io
|
||||
// - https://hold01.atcr.io → did:web:hold01.atcr.io
|
||||
// - did:web:hold01.atcr.io → did:web:hold01.atcr.io (passthrough)
|
||||
func ResolveHoldDIDFromURL(holdURL string) string {
|
||||
// Handle empty URLs
|
||||
if holdURL == "" {
|
||||
@@ -415,7 +418,7 @@ func ResolveHoldDIDFromURL(holdURL string) string {
|
||||
}
|
||||
|
||||
// If already a DID, return as-is
|
||||
if strings.HasPrefix(holdURL, "did:") {
|
||||
if IsDID(holdURL) {
|
||||
return holdURL
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
type App struct {
|
||||
clientApp *oauth.ClientApp
|
||||
baseURL string
|
||||
directory identity.Directory
|
||||
}
|
||||
|
||||
// NewApp creates a new OAuth app for ATCR with default scopes
|
||||
@@ -32,11 +31,11 @@ func NewApp(baseURL string, store oauth.ClientAuthStore, holdDid string, testMod
|
||||
func NewAppWithScopes(baseURL string, store oauth.ClientAuthStore, scopes []string) (*App, error) {
|
||||
config := NewClientConfigWithScopes(baseURL, scopes)
|
||||
clientApp := oauth.NewClientApp(&config, store)
|
||||
clientApp.Dir = atproto.GetDirectory()
|
||||
|
||||
return &App{
|
||||
clientApp: clientApp,
|
||||
baseURL: baseURL,
|
||||
directory: atproto.GetDirectory(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -102,7 +101,7 @@ func (a *App) GetClientApp() *oauth.ClientApp {
|
||||
|
||||
// Directory returns the identity directory used by the OAuth app
|
||||
func (a *App) Directory() identity.Directory {
|
||||
return a.directory
|
||||
return a.clientApp.Dir
|
||||
}
|
||||
|
||||
// ClientIDWithScopes generates a client ID with custom scopes
|
||||
|
||||
@@ -263,7 +263,7 @@ func (h *XRPCHandler) HandleGetProfile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Normalize actor to DID
|
||||
actorDID := actor
|
||||
if !strings.HasPrefix(actor, "did:") {
|
||||
if !atproto.IsDID(actor) {
|
||||
// It's a handle, resolve to DID
|
||||
expectedHandle := strings.TrimPrefix(h.pds.DID(), "did:web:")
|
||||
if actor == expectedHandle {
|
||||
@@ -306,7 +306,7 @@ func (h *XRPCHandler) HandleGetProfiles(w http.ResponseWriter, r *http.Request)
|
||||
for _, actor := range actors {
|
||||
// Normalize actor to DID
|
||||
actorDID := actor
|
||||
if !strings.HasPrefix(actor, "did:") {
|
||||
if !atproto.IsDID(actor) {
|
||||
// It's a handle, check if it matches
|
||||
if actor == expectedHandle {
|
||||
actorDID = h.pds.DID()
|
||||
|
||||
Reference in New Issue
Block a user