A community based topic aggregation platform built on atproto
at main 69 lines 3.4 kB view raw
1package userblocks 2 3import ( 4 "Coves/internal/atproto/pds" 5 "context" 6 7 "github.com/bluesky-social/indigo/atproto/auth/oauth" 8) 9 10// PDSClientFactory creates PDS clients from session data. 11// This is primarily used for test injection via NewServiceWithPDSFactory to allow 12// password-based auth in integration tests instead of OAuth DPoP. 13type PDSClientFactory func(ctx context.Context, session *oauth.ClientSessionData) (pds.Client, error) 14 15// Repository defines the interface for user block data persistence. 16// This is the AppView's indexed view of blocks from the firehose. 17type Repository interface { 18 // BlockUser creates a new block record (idempotent via ON CONFLICT DO UPDATE) 19 BlockUser(ctx context.Context, block *UserBlock) (*UserBlock, error) 20 21 // UnblockUser removes a block record. Returns ErrBlockNotFound if not exists. 22 UnblockUser(ctx context.Context, blockerDID, blockedDID string) error 23 24 // GetBlock retrieves a block by blocker + blocked DID pair. 25 // Returns ErrBlockNotFound if not exists. 26 GetBlock(ctx context.Context, blockerDID, blockedDID string) (*UserBlock, error) 27 28 // GetBlockByURI retrieves a block by its AT-URI. 29 // Used by Jetstream consumer for DELETE operations (which don't include record data). 30 // Returns ErrBlockNotFound if not exists. 31 GetBlockByURI(ctx context.Context, recordURI string) (*UserBlock, error) 32 33 // ListBlockedUsers retrieves all users blocked by the given blocker, paginated. 34 // Results are ordered by blocked_at DESC. 35 ListBlockedUsers(ctx context.Context, blockerDID string, limit, offset int) ([]*UserBlock, error) 36 37 // IsBlocked checks if blockerDID has blocked blockedDID (fast EXISTS check). 38 IsBlocked(ctx context.Context, blockerDID, blockedDID string) (bool, error) 39 40 // AreBlocked checks which of the given DIDs are blocked by blockerDID. 41 // Returns a map of blockedDID → true for each DID that is blocked. 42 // Used for batch hydration of viewer state on lists of posts/comments. 43 AreBlocked(ctx context.Context, blockerDID string, blockedDIDs []string) (map[string]bool, error) 44} 45 46// Service defines the interface for user block business logic. 47// Coordinates between Repository and external services (PDS, identity, etc.) 48// Uses write-forward pattern: Service → PDS → Firehose → Consumer → Repository 49type Service interface { 50 // BlockUser creates a block against another user. 51 // Uses OAuth session for DPoP-authenticated PDS write-forward. 52 // The identifier can be a DID or handle. 53 // Returns a BlockResult with the record URI and CID from PDS. 54 // The block is indexed asynchronously via the firehose consumer. 55 // Returns ErrCannotBlockSelf if the user attempts to block themselves. 56 // Returns ErrBlockAlreadyExists if the block already exists on PDS. 57 BlockUser(ctx context.Context, session *oauth.ClientSessionData, identifier string) (*BlockResult, error) 58 59 // UnblockUser removes a block against another user. 60 // Uses OAuth session for DPoP-authenticated PDS delete. 61 // The identifier can be a DID or handle. 62 UnblockUser(ctx context.Context, session *oauth.ClientSessionData, identifier string) error 63 64 // GetBlockedUsers retrieves all users blocked by the given user, paginated. 65 GetBlockedUsers(ctx context.Context, blockerDID string, limit, offset int) ([]*UserBlock, error) 66 67 // IsBlocked checks if blockerDID has blocked blockedDID. 68 IsBlocked(ctx context.Context, blockerDID, blockedDID string) (bool, error) 69}