diff --git a/pkg/handler/post_test.go b/pkg/handler/post_test.go index cd5aba63..a5cd6b9d 100644 --- a/pkg/handler/post_test.go +++ b/pkg/handler/post_test.go @@ -599,6 +599,48 @@ func TestPost(t *testing.T) { }, }).Run(handler, t) }) + + SubTest(t, "RejectAccessConcat", func(t *testing.T, store *MockFullDataStore, composer *StoreComposer) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + uploadA := NewMockFullUpload(ctrl) + uploadB := NewMockFullUpload(ctrl) + + gomock.InOrder( + store.EXPECT().GetUpload(gomock.Any(), "a").Return(uploadA, nil), + uploadA.EXPECT().GetInfo(gomock.Any()).Return(FileInfo{ + ID: "a", + Offset: 5, + Size: 5, + }, nil), + + store.EXPECT().GetUpload(gomock.Any(), "b").Return(uploadB, nil), + uploadB.EXPECT().GetInfo(gomock.Any()).Return(FileInfo{ + ID: "b", + Offset: 10, + Size: 10, + }, nil), + ) + + handler, _ := NewHandler(Config{ + StoreComposer: composer, + BasePath: "/files/", + PreUploadCreateCallback: func(event HookEvent) (HTTPResponse, FileInfoChanges, error) { + return HTTPResponse{}, FileInfoChanges{}, ErrAccessRejectedByServer + }, + }) + + (&httpTest{ + Method: "POST", + ReqHeader: map[string]string{ + "Tus-Resumable": "1.0.0", + "Upload-Concat": "final;http://tus.io/files/a http://tus.io/files/b", + }, + Code: ErrAccessRejectedByServer.HTTPResponse.StatusCode, + ResHeader: ErrAccessRejectedByServer.HTTPResponse.Header, + ResBody: ErrAccessRejectedByServer.HTTPResponse.Body, + }).Run(handler, t) + }) }) SubTest(t, "ExperimentalProtocol", func(t *testing.T, _ *MockFullDataStore, _ *StoreComposer) { diff --git a/pkg/handler/unrouted_handler.go b/pkg/handler/unrouted_handler.go index 3807b4cc..a151b81e 100644 --- a/pkg/handler/unrouted_handler.go +++ b/pkg/handler/unrouted_handler.go @@ -293,6 +293,7 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) var size int64 var sizeIsDeferred bool var partialUploads []Upload + var partialFileInfos []FileInfo if isFinal { // A final upload must not contain a chunk within the creation request if containsChunk { @@ -300,7 +301,7 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) return } - partialUploads, size, err = handler.sizeOfUploads(c, partialUploadIDs) + partialUploads, partialFileInfos, size, err = handler.sizeOfUploads(c, partialUploadIDs) if err != nil { handler.sendError(c, err) return @@ -339,7 +340,8 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) } if handler.config.PreUploadCreateCallback != nil { - resp2, changes, err := handler.config.PreUploadCreateCallback(newHookEvent(c, &info, nil)) + access := newAccessInfo(AccessModeRead, partialFileInfos) + resp2, changes, err := handler.config.PreUploadCreateCallback(newHookEvent(c, &info, &access)) if err != nil { handler.sendError(c, err) return @@ -1310,27 +1312,29 @@ func getHostAndProtocol(r *http.Request, allowForwarded bool) (host, proto strin // The get sum of all sizes for a list of upload ids while checking whether // all of these uploads are finished yet. This is used to calculate the size // of a final resource. -func (handler *UnroutedHandler) sizeOfUploads(ctx context.Context, ids []string) (partialUploads []Upload, size int64, err error) { +func (handler *UnroutedHandler) sizeOfUploads(ctx context.Context, ids []string) (partialUploads []Upload, partialFileInfos []FileInfo, size int64, err error) { partialUploads = make([]Upload, len(ids)) + partialFileInfos = make([]FileInfo, len(ids)) for i, id := range ids { upload, err := handler.composer.Core.GetUpload(ctx, id) if err != nil { - return nil, 0, err + return nil, nil, 0, err } info, err := upload.GetInfo(ctx) if err != nil { - return nil, 0, err + return nil, nil, 0, err } if info.SizeIsDeferred || info.Offset != info.Size { err = ErrUploadNotFinished - return nil, 0, err + return nil, nil, 0, err } size += info.Size partialUploads[i] = upload + partialFileInfos[i] = info } return