1package server
2
3import (
4 "bytes"
5
6 "github.com/Azure/go-autorest/autorest/to"
7 "github.com/haileyok/cocoon/internal/helpers"
8 "github.com/haileyok/cocoon/models"
9 "github.com/ipfs/go-cid"
10 "github.com/labstack/echo/v4"
11)
12
13func (s *Server) handleSyncGetBlob(e echo.Context) error {
14 did := e.QueryParam("did")
15 if did == "" {
16 return helpers.InputError(e, nil)
17 }
18
19 cstr := e.QueryParam("cid")
20 if cstr == "" {
21 return helpers.InputError(e, nil)
22 }
23
24 c, err := cid.Parse(cstr)
25 if err != nil {
26 return helpers.InputError(e, nil)
27 }
28
29 urepo, err := s.getRepoActorByDid(did)
30 if err != nil {
31 s.logger.Error("could not find user for requested blob", "error", err)
32 return helpers.InputError(e, nil)
33 }
34
35 status := urepo.Status()
36 if status != nil {
37 if *status == "deactivated" {
38 return helpers.InputError(e, to.StringPtr("RepoDeactivated"))
39 }
40 }
41
42 var blob models.Blob
43 if err := s.db.Raw("SELECT * FROM blobs WHERE did = ? AND cid = ?", nil, did, c.Bytes()).Scan(&blob).Error; err != nil {
44 s.logger.Error("error looking up blob", "error", err)
45 return helpers.ServerError(e, nil)
46 }
47
48 buf := new(bytes.Buffer)
49
50 var parts []models.BlobPart
51 if err := s.db.Raw("SELECT * FROM blob_parts WHERE blob_id = ? ORDER BY idx", nil, blob.ID).Scan(&parts).Error; err != nil {
52 s.logger.Error("error getting blob parts", "error", err)
53 return helpers.ServerError(e, nil)
54 }
55
56 // TODO: we can just stream this, don't need to make a buffer
57 for _, p := range parts {
58 buf.Write(p.Data)
59 }
60
61 e.Response().Header().Set(echo.HeaderContentDisposition, "attachment; filename="+c.String())
62
63 return e.Stream(200, "application/octet-stream", buf)
64}