Monorepo for Tangled

appview,xrpc: rewrite RepoUploadBlob to accept content types

uploading a blob without the content type results in a 403
ScopeMissingError, but indigo does not let us specify one! rewriting the
API to allow specifying the blob mime type is a temporary fix until
upstream allows this.

Signed-off-by: oppiliappan <me@oppi.li>

authored by

oppiliappan and committed by tangled.org c2049613 c983de83

+38 -14
+8 -5
appview/pulls/pulls.go
··· 39 39 "tangled.org/core/rbac" 40 40 "tangled.org/core/tid" 41 41 "tangled.org/core/types" 42 + "tangled.org/core/xrpc" 42 43 43 44 comatproto "github.com/bluesky-social/indigo/api/atproto" 44 45 "github.com/bluesky-social/indigo/atproto/syntax" ··· 47 48 "github.com/go-chi/chi/v5" 48 49 "github.com/google/uuid" 49 50 ) 51 + 52 + const ApplicationGzip = "application/gzip" 50 53 51 54 type Pulls struct { 52 55 oauth *oauth.OAuth ··· 1227 1230 return 1228 1231 } 1229 1232 1230 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(patch)) 1233 + blob, err := xrpc.RepoUploadBlob(r.Context(), client, gz(patch), ApplicationGzip) 1231 1234 if err != nil { 1232 1235 log.Println("failed to upload patch", err) 1233 1236 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") ··· 1321 1324 // apply all record creations at once 1322 1325 var writes []*comatproto.RepoApplyWrites_Input_Writes_Elem 1323 1326 for _, p := range stack { 1324 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(p.LatestPatch())) 1327 + blob, err := xrpc.RepoUploadBlob(r.Context(), client, gz(p.LatestPatch()), ApplicationGzip) 1325 1328 if err != nil { 1326 1329 log.Println("failed to upload patch blob", err) 1327 1330 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") ··· 1871 1874 return 1872 1875 } 1873 1876 1874 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(patch)) 1877 + blob, err := xrpc.RepoUploadBlob(r.Context(), client, gz(patch), ApplicationGzip) 1875 1878 if err != nil { 1876 1879 log.Println("failed to upload patch blob", err) 1877 1880 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.") ··· 2014 2017 return 2015 2018 } 2016 2019 2017 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(patch)) 2020 + blob, err := xrpc.RepoUploadBlob(r.Context(), client, gz(patch), ApplicationGzip) 2018 2021 if err != nil { 2019 2022 log.Println("failed to upload patch blob", err) 2020 2023 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.") ··· 2056 2059 return 2057 2060 } 2058 2061 2059 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(patch)) 2062 + blob, err := xrpc.RepoUploadBlob(r.Context(), client, gz(patch), ApplicationGzip) 2060 2063 if err != nil { 2061 2064 log.Println("failed to upload patch blob", err) 2062 2065 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.")
+5 -4
appview/repo/artifact.go
··· 18 18 "tangled.org/core/orm" 19 19 "tangled.org/core/tid" 20 20 "tangled.org/core/types" 21 + "tangled.org/core/xrpc" 21 22 22 23 comatproto "github.com/bluesky-social/indigo/api/atproto" 23 24 lexutil "github.com/bluesky-social/indigo/lex/util" ··· 46 47 return 47 48 } 48 49 49 - file, handler, err := r.FormFile("artifact") 50 + file, header, err := r.FormFile("artifact") 50 51 if err != nil { 51 52 log.Println("failed to upload artifact", err) 52 53 rp.pages.Notice(w, "upload", "failed to upload artifact") ··· 61 62 return 62 63 } 63 64 64 - uploadBlobResp, err := comatproto.RepoUploadBlob(r.Context(), client, file) 65 + uploadBlobResp, err := xrpc.RepoUploadBlob(r.Context(), client, file, header.Header.Get("Content-Type")) 65 66 if err != nil { 66 67 log.Println("failed to upload blob", err) 67 68 rp.pages.Notice(w, "upload", "Failed to upload blob to your PDS. Try again later.") ··· 81 82 Val: &tangled.RepoArtifact{ 82 83 Artifact: uploadBlobResp.Blob, 83 84 CreatedAt: createdAt.Format(time.RFC3339), 84 - Name: handler.Filename, 85 + Name: header.Filename, 85 86 Repo: f.RepoAt().String(), 86 87 Tag: tag.Tag.Hash[:], 87 88 }, ··· 110 111 Tag: tag.Tag.Hash, 111 112 CreatedAt: createdAt, 112 113 BlobCid: cid.Cid(uploadBlobResp.Blob.Ref), 113 - Name: handler.Filename, 114 + Name: header.Filename, 114 115 Size: uint64(uploadBlobResp.Blob.Size), 115 116 MimeType: uploadBlobResp.Blob.MimeType, 116 117 }
+6 -5
appview/state/profile.go
··· 20 20 "tangled.org/core/appview/models" 21 21 "tangled.org/core/appview/pages" 22 22 "tangled.org/core/orm" 23 + "tangled.org/core/xrpc" 23 24 ) 24 25 25 26 func (s *State) Profile(w http.ResponseWriter, r *http.Request) { ··· 741 742 return 742 743 } 743 744 744 - file, handler, err := r.FormFile("avatar") 745 + file, header, err := r.FormFile("avatar") 745 746 if err != nil { 746 747 l.Error("failed to read avatar file", "err", err) 747 748 s.pages.Notice(w, "avatar-error", "Failed to read avatar file") ··· 749 750 } 750 751 defer file.Close() 751 752 752 - if handler.Size > 1000000 { 753 - l.Warn("avatar file too large", "size", handler.Size) 753 + if header.Size > 1000000 { 754 + l.Warn("avatar file too large", "size", header.Size) 754 755 s.pages.Notice(w, "avatar-error", "Avatar file too large (max 1MB)") 755 756 return 756 757 } 757 758 758 - contentType := handler.Header.Get("Content-Type") 759 + contentType := header.Header.Get("Content-Type") 759 760 if contentType != "image/png" && contentType != "image/jpeg" { 760 761 l.Warn("invalid image type", "contentType", contentType) 761 762 s.pages.Notice(w, "avatar-error", "Invalid image type (only PNG and JPEG allowed)") ··· 769 770 return 770 771 } 771 772 772 - uploadBlobResp, err := comatproto.RepoUploadBlob(r.Context(), client, file) 773 + uploadBlobResp, err := xrpc.RepoUploadBlob(r.Context(), client, file, header.Header.Get("Content-Type")) 773 774 if err != nil { 774 775 l.Error("failed to upload avatar blob", "err", err) 775 776 s.pages.Notice(w, "avatar-error", "Failed to upload avatar to your PDS")
+19
xrpc/blob.go
··· 1 + package xrpc 2 + 3 + import ( 4 + "context" 5 + "io" 6 + 7 + comatproto "github.com/bluesky-social/indigo/api/atproto" 8 + "github.com/bluesky-social/indigo/lex/util" 9 + ) 10 + 11 + // RepoUploadBlob calls the XRPC method "com.atproto.repo.uploadBlob". 12 + func RepoUploadBlob(ctx context.Context, c util.LexClient, input io.Reader, contentType string) (*comatproto.RepoUploadBlob_Output, error) { 13 + var out comatproto.RepoUploadBlob_Output 14 + if err := c.LexDo(ctx, util.Procedure, contentType, "com.atproto.repo.uploadBlob", nil, input, &out); err != nil { 15 + return nil, err 16 + } 17 + 18 + return &out, nil 19 + }