BYOK Personal Data Server (PDS) written in Go
ipfs vow atproto pds go
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Use offline IPFS client and handle empty repo roots

+44 -12
+10 -6
blockstore/ipfs.go
··· 12 12 blocks "github.com/ipfs/go-block-format" 13 13 "github.com/ipfs/go-cid" 14 14 "github.com/ipfs/kubo/client/rpc" 15 + "github.com/ipfs/kubo/core/coreiface" 15 16 caopts "github.com/ipfs/kubo/core/coreiface/options" 16 17 "github.com/multiformats/go-multicodec" 17 18 ) ··· 21 22 did string 22 23 rev string 23 24 cli *rpc.HttpApi 25 + offlineCli iface.CoreAPI 24 26 25 27 mu sync.RWMutex 26 28 inserts map[cid.Cid]blocks.Block ··· 28 30 29 31 // NewIPFS creates a blockstore. 30 32 func NewIPFS(did string, cli *rpc.HttpApi) *IPFSBlockstore { 33 + offlineCli, _ := cli.WithOptions(caopts.Api.Offline(true)) 31 34 return &IPFSBlockstore{ 32 - did: did, 33 - cli: cli, 34 - inserts: make(map[cid.Cid]blocks.Block), 35 + did: did, 36 + cli: cli, 37 + offlineCli: offlineCli, 38 + inserts: make(map[cid.Cid]blocks.Block), 35 39 } 36 40 } 37 41 ··· 50 54 bs.mu.RUnlock() 51 55 52 56 p := path.FromCid(c) 53 - r, err := bs.cli.Block().Get(ctx, p) 57 + r, err := bs.offlineCli.Block().Get(ctx, p) 54 58 if err != nil { 55 59 return nil, fmt.Errorf("ipfs block/get: %w", err) 56 60 } ··· 128 132 bs.mu.RUnlock() 129 133 130 134 p := path.FromCid(c) 131 - _, err := bs.cli.Block().Stat(ctx, p) 135 + _, err := bs.offlineCli.Block().Stat(ctx, p) 132 136 if err != nil { 133 137 // Not found error means block doesn't exist 134 138 return false, nil ··· 179 183 // Verify checks that a block exists in IPFS, bypassing the local cache. 180 184 func (bs *IPFSBlockstore) Verify(ctx context.Context, c cid.Cid) error { 181 185 p := path.FromCid(c) 182 - _, err := bs.cli.Block().Stat(ctx, p) 186 + _, err := bs.offlineCli.Block().Stat(ctx, p) 183 187 if err != nil { 184 188 return fmt.Errorf("ipfs block/stat %s: %w", c, err) 185 189 }
+4
server/handle_repo_list_repos.go
··· 56 56 57 57 items := make([]ComAtprotoSyncListReposRepoItem, 0, len(repos)) 58 58 for _, repo := range repos { 59 + if len(repo.Root) == 0 { 60 + continue 61 + } 62 + 59 63 c, err := cid.Cast(repo.Root) 60 64 if err != nil { 61 65 helpers.ServerError(w, nil)
+8 -6
server/handle_server_check_account_status.go
··· 32 32 RepoRev: urepo.Rev, 33 33 } 34 34 35 - rootcid, err := cid.Cast(urepo.Root) 36 - if err != nil { 37 - logger.Error("error casting cid", "error", err) 38 - helpers.ServerError(w, nil) 39 - return 35 + if len(urepo.Root) > 0 { 36 + rootcid, err := cid.Cast(urepo.Root) 37 + if err != nil { 38 + logger.Error("error casting cid", "error", err) 39 + helpers.ServerError(w, nil) 40 + return 41 + } 42 + resp.RepoCommit = rootcid.String() 40 43 } 41 - resp.RepoCommit = rootcid.String() 42 44 43 45 type CountResp struct { 44 46 Ct int64
+7
server/handle_sync_get_blocks.go
··· 46 46 return 47 47 } 48 48 49 + if len(urepo.Root) == 0 { 50 + logger.Error("repo root is uninitialized", "did", did) 51 + errStr := "RepoNotFound" 52 + helpers.InputError(w, &errStr) 53 + return 54 + } 55 + 49 56 rc, err := cid.Cast(urepo.Root) 50 57 if err != nil { 51 58 logger.Error("error casting root cid", "error", err)
+7
server/handle_sync_get_latest_commit.go
··· 29 29 return 30 30 } 31 31 32 + if len(urepo.Root) == 0 { 33 + logger.Error("repo root is uninitialized", "did", did) 34 + errStr := "RepoNotFound" 35 + helpers.InputError(w, &errStr) 36 + return 37 + } 38 + 32 39 c, err := cid.Cast(urepo.Root) 33 40 if err != nil { 34 41 logger.Error("could not cast root cid", "error", err)
+8
server/handle_sync_get_repo.go
··· 30 30 return 31 31 } 32 32 33 + if len(urepo.Root) == 0 { 34 + logger.Error("repo root is uninitialized", "did", did) 35 + // 400 is appropriate for RepoNotFound in ATProto 36 + errStr := "RepoNotFound" 37 + helpers.InputError(w, &errStr) 38 + return 39 + } 40 + 33 41 rc, err := cid.Cast(urepo.Root) 34 42 if err != nil { 35 43 logger.Error("error casting root cid", "error", err)