remove older endpoints add docs for blob migration to xrpc

This commit is contained in:
Evan Jarrett
2025-10-16 21:34:55 -05:00
parent 7cf6da09f9
commit 003dab263d
5 changed files with 675 additions and 140 deletions
-91
View File
@@ -8,8 +8,6 @@ import (
"log"
"net/http"
"time"
"atcr.io/pkg/atproto"
)
// PresignedURLOperation defines the type of presigned URL operation
@@ -496,92 +494,3 @@ func (s *HoldService) HandleAbortMultipart(w http.ResponseWriter, r *http.Reques
"status": "aborted",
})
}
// RegisterRequest represents a request to register this hold in a user's PDS
type RegisterRequest struct {
DID string `json:"did"`
AccessToken string `json:"access_token"`
PDSEndpoint string `json:"pds_endpoint"`
}
// RegisterResponse contains the registration result
type RegisterResponse struct {
HoldURI string `json:"hold_uri"`
CrewURI string `json:"crew_uri"`
Message string `json:"message"`
}
// HandleRegister registers this hold service in a user's PDS (manual endpoint)
func (s *HoldService) HandleRegister(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
var req RegisterRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, fmt.Sprintf("invalid request: %v", err), http.StatusBadRequest)
return
}
// Validate required fields
if req.DID == "" || req.AccessToken == "" || req.PDSEndpoint == "" {
http.Error(w, "missing required fields: did, access_token, pds_endpoint", http.StatusBadRequest)
return
}
// Get public URL from config
publicURL := s.config.Server.PublicURL
if publicURL == "" {
// Fallback to constructing URL from request
scheme := "http"
if r.TLS != nil {
scheme = "https"
}
publicURL = fmt.Sprintf("%s://%s", scheme, r.Host)
}
// Derive hold name from URL
holdName, err := extractHostname(publicURL)
if err != nil {
http.Error(w, fmt.Sprintf("failed to extract hostname: %v", err), http.StatusBadRequest)
return
}
ctx := r.Context()
// Create ATProto client with user's credentials
client := atproto.NewClient(req.PDSEndpoint, req.DID, req.AccessToken)
// Create HoldRecord
holdRecord := atproto.NewHoldRecord(publicURL, req.DID, s.config.Server.Public)
holdResult, err := client.PutRecord(ctx, atproto.HoldCollection, holdName, holdRecord)
if err != nil {
http.Error(w, fmt.Sprintf("failed to create hold record: %v", err), http.StatusInternalServerError)
return
}
log.Printf("Created hold record: %s", holdResult.URI)
// Create HoldCrewRecord for the owner
crewRecord := atproto.NewHoldCrewRecord(holdResult.URI, req.DID, "owner")
crewRKey := fmt.Sprintf("%s-%s", holdName, req.DID)
crewResult, err := client.PutRecord(ctx, atproto.HoldCrewCollection, crewRKey, crewRecord)
if err != nil {
http.Error(w, fmt.Sprintf("failed to create crew record: %v", err), http.StatusInternalServerError)
return
}
log.Printf("Created crew record: %s", crewResult.URI)
resp := RegisterResponse{
HoldURI: holdResult.URI,
CrewURI: crewResult.URI,
Message: fmt.Sprintf("Successfully registered hold service. Storage endpoint: %s", publicURL),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(resp)
}
-40
View File
@@ -1,40 +0,0 @@
package hold
import (
"regexp"
"strings"
)
// matchPattern checks if a handle matches a pattern
// Supports wildcards: "*" (all), "*.domain.com" (suffix), "prefix.*" (prefix), "*.mid.*" (contains)
func matchPattern(pattern, handle string) bool {
if pattern == "*" {
// Wildcard matches all
return true
}
// Convert glob to regex and match
regex := globToRegex(pattern)
matched, err := regexp.MatchString(regex, handle)
if err != nil {
// Log error but fail closed (don't grant access on regex error)
return false
}
return matched
}
// globToRegex converts a glob pattern to a regex pattern
// Examples:
// - "*.example.com" → "^.*\.example\.com$"
// - "subdomain.*" → "^subdomain\..*$"
// - "*.bsky.*" → "^.*\.bsky\..*$"
func globToRegex(pattern string) string {
// Escape special regex characters (except *)
escaped := regexp.QuoteMeta(pattern)
// Replace escaped \* with .*
regex := strings.ReplaceAll(escaped, "\\*", ".*")
// Anchor to start and end
return "^" + regex + "$"
}
-7
View File
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"log"
"net/http"
"net/url"
"atcr.io/pkg/auth"
@@ -96,12 +95,6 @@ func (s *HoldService) isAuthorizedWrite(did string) bool {
return allowed
}
// HealthHandler handles health check requests
func (s *HoldService) HealthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"ok"}`))
}
// extractHostname extracts the hostname from a URL
func extractHostname(urlStr string) (string, error) {
u, err := url.Parse(urlStr)