mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-10 04:06:06 +00:00
big scary refactor. sync enable_bluesky_posts with captain record. implement oauth logout handler. implement crew assignment to hold. this caused a lot of circular dependencies and needed to move functions around in order to fix
This commit is contained in:
+38
-31
@@ -1,6 +1,7 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -11,30 +12,38 @@ import (
|
||||
"github.com/bluesky-social/indigo/atproto/syntax"
|
||||
|
||||
"atcr.io/pkg/appview/db"
|
||||
mainAtproto "atcr.io/pkg/atproto"
|
||||
"atcr.io/pkg/auth"
|
||||
)
|
||||
|
||||
// PostAuthCallback is called after successful Basic Auth authentication.
|
||||
// Parameters: ctx, did, handle, pdsEndpoint, accessToken
|
||||
// This allows AppView to perform business logic (profile creation, etc.)
|
||||
// without coupling the token package to AppView-specific dependencies.
|
||||
type PostAuthCallback func(ctx context.Context, did, handle, pdsEndpoint, accessToken string) error
|
||||
|
||||
// Handler handles /auth/token requests
|
||||
type Handler struct {
|
||||
issuer *Issuer
|
||||
validator *auth.SessionValidator
|
||||
deviceStore *db.DeviceStore // For validating device secrets
|
||||
defaultHoldDID string
|
||||
issuer *Issuer
|
||||
validator *auth.SessionValidator
|
||||
deviceStore *db.DeviceStore // For validating device secrets
|
||||
postAuthCallback PostAuthCallback
|
||||
}
|
||||
|
||||
// NewHandler creates a new token handler
|
||||
// defaultHoldDID should be in format "did:web:hold01.atcr.io"
|
||||
// To find a hold's DID, visit: https://hold-url/.well-known/did.json
|
||||
func NewHandler(issuer *Issuer, deviceStore *db.DeviceStore, defaultHoldDID string) *Handler {
|
||||
func NewHandler(issuer *Issuer, deviceStore *db.DeviceStore) *Handler {
|
||||
return &Handler{
|
||||
issuer: issuer,
|
||||
validator: auth.NewSessionValidator(),
|
||||
deviceStore: deviceStore,
|
||||
defaultHoldDID: defaultHoldDID,
|
||||
issuer: issuer,
|
||||
validator: auth.NewSessionValidator(),
|
||||
deviceStore: deviceStore,
|
||||
}
|
||||
}
|
||||
|
||||
// SetPostAuthCallback sets the callback to be invoked after successful Basic Auth authentication
|
||||
// This allows AppView to inject business logic without coupling the token package
|
||||
func (h *Handler) SetPostAuthCallback(callback PostAuthCallback) {
|
||||
h.postAuthCallback = callback
|
||||
}
|
||||
|
||||
// TokenResponse represents the response from /auth/token
|
||||
type TokenResponse struct {
|
||||
Token string `json:"token,omitempty"` // Legacy field
|
||||
@@ -142,25 +151,23 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
auth.GetGlobalTokenCache().Set(did, accessToken, 2*time.Hour)
|
||||
fmt.Printf("DEBUG [token/handler]: Cached access token for DID=%s\n", did)
|
||||
|
||||
// Ensure user profile exists (creates with default hold if needed)
|
||||
// Resolve PDS endpoint for profile management
|
||||
directory := identity.DefaultDirectory()
|
||||
atID, err := syntax.ParseAtIdentifier(username)
|
||||
if err == nil {
|
||||
ident, err := directory.Lookup(r.Context(), *atID)
|
||||
if err != nil {
|
||||
// Log error but don't fail auth - profile management is not critical
|
||||
fmt.Printf("WARNING: failed to resolve PDS for profile management: %v\n", err)
|
||||
} else {
|
||||
pdsEndpoint := ident.PDSEndpoint()
|
||||
if pdsEndpoint != "" {
|
||||
// Create ATProto client with validated token
|
||||
atprotoClient := mainAtproto.NewClient(pdsEndpoint, did, accessToken)
|
||||
|
||||
// Ensure profile exists (will create with default hold if not exists and default is configured)
|
||||
if err := mainAtproto.EnsureProfile(r.Context(), atprotoClient, h.defaultHoldDID); err != nil {
|
||||
// Log error but don't fail auth - profile management is not critical
|
||||
fmt.Printf("WARNING: failed to ensure profile for %s: %v\n", did, err)
|
||||
// Call post-auth callback for AppView business logic (profile management, etc.)
|
||||
if h.postAuthCallback != nil {
|
||||
// Resolve PDS endpoint for callback
|
||||
directory := identity.DefaultDirectory()
|
||||
atID, err := syntax.ParseAtIdentifier(username)
|
||||
if err == nil {
|
||||
ident, err := directory.Lookup(r.Context(), *atID)
|
||||
if err != nil {
|
||||
// Log error but don't fail auth - profile management is not critical
|
||||
fmt.Printf("WARNING: failed to resolve PDS for callback: %v\n", err)
|
||||
} else {
|
||||
pdsEndpoint := ident.PDSEndpoint()
|
||||
if pdsEndpoint != "" {
|
||||
if err := h.postAuthCallback(r.Context(), did, handle, pdsEndpoint, accessToken); err != nil {
|
||||
// Log error but don't fail auth - business logic is non-critical
|
||||
fmt.Printf("WARNING: post-auth callback failed for DID=%s: %v\n", did, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user