diff --git a/changelog/unreleased/dav-error-codes.md b/changelog/unreleased/dav-error-codes.md new file mode 100644 index 0000000000..d952c74629 --- /dev/null +++ b/changelog/unreleased/dav-error-codes.md @@ -0,0 +1,6 @@ +Enhancement: DAV error codes + +DAV error responses now include an error code for clients to use if they need to check for a specific error type. + +https://github.com/cs3org/reva/pull/4749 +https://github.com/owncloud/ocis/issues/9533 diff --git a/internal/http/services/owncloud/ocdav/copy.go b/internal/http/services/owncloud/ocdav/copy.go index 4ac02d4f4c..2ebd66ef9b 100644 --- a/internal/http/services/owncloud/ocdav/copy.go +++ b/internal/http/services/owncloud/ocdav/copy.go @@ -58,7 +58,7 @@ func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string) if r.Body != http.NoBody { w.WriteHeader(http.StatusUnsupportedMediaType) - b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "") + b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } @@ -83,21 +83,21 @@ func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string) dst, err := net.ParseDestination(baseURI, dh) if err != nil { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, "failed to extract destination", "") + b, err := errors.Marshal(http.StatusBadRequest, "failed to extract destination", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } if err := ValidateName(filename(src), s.nameValidators); err != nil { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, "source failed naming rules", "") + b, err := errors.Marshal(http.StatusBadRequest, "source failed naming rules", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } if err := ValidateDestination(filename(dst), s.nameValidators); err != nil { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, "destination failed naming rules", "") + b, err := errors.Marshal(http.StatusBadRequest, "destination failed naming rules", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } @@ -163,7 +163,7 @@ func (s *svc) executePathCopy(ctx context.Context, selector pool.Selectable[gate if createRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED { w.WriteHeader(http.StatusForbidden) m := fmt.Sprintf("Permission denied to create %v", createReq.Ref.Path) - b, err := errors.Marshal(http.StatusForbidden, m, "") + b, err := errors.Marshal(http.StatusForbidden, m, "", "") errors.HandleWebdavError(log, w, b, err) } return nil @@ -264,7 +264,7 @@ func (s *svc) executePathCopy(ctx context.Context, selector pool.Selectable[gate if uRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED { w.WriteHeader(http.StatusForbidden) m := fmt.Sprintf("Permissions denied to create %v", uReq.Ref.Path) - b, err := errors.Marshal(http.StatusForbidden, m, "") + b, err := errors.Marshal(http.StatusForbidden, m, "", "") errors.HandleWebdavError(log, w, b, err) return nil } @@ -327,7 +327,7 @@ func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID s if r.Body != http.NoBody { w.WriteHeader(http.StatusUnsupportedMediaType) - b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "") + b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } @@ -394,7 +394,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, sele w.WriteHeader(http.StatusForbidden) // TODO path could be empty or relative... m := fmt.Sprintf("Permission denied to create %v", createReq.Ref.Path) - b, err := errors.Marshal(http.StatusForbidden, m, "") + b, err := errors.Marshal(http.StatusForbidden, m, "", "") errors.HandleWebdavError(log, w, b, err) } return nil @@ -482,7 +482,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, sele w.WriteHeader(http.StatusForbidden) // TODO path can be empty or relative m := fmt.Sprintf("Permissions denied to create %v", uReq.Ref.Path) - b, err := errors.Marshal(http.StatusForbidden, m, "") + b, err := errors.Marshal(http.StatusForbidden, m, "", "") errors.HandleWebdavError(log, w, b, err) return nil } @@ -554,7 +554,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re } if isChild { w.WriteHeader(http.StatusConflict) - b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into one of its children", "") + b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into one of its children", "", "") errors.HandleWebdavError(log, w, b, err) return nil } @@ -577,7 +577,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re if isParent { w.WriteHeader(http.StatusConflict) - b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into its parent", "") + b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into its parent", "", "") errors.HandleWebdavError(log, w, b, err) return nil @@ -585,7 +585,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re if srcRef.Path == dstRef.Path && srcRef.ResourceId == dstRef.ResourceId { w.WriteHeader(http.StatusConflict) - b, err := errors.Marshal(http.StatusBadRequest, "source and destination are the same", "") + b, err := errors.Marshal(http.StatusBadRequest, "source and destination are the same", "", "") errors.HandleWebdavError(log, w, b, err) return nil } @@ -595,7 +595,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re if err != nil { w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Overwrite header is set to incorrect value %v", overwrite) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(log, w, b, err) return nil } @@ -605,7 +605,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re if err != nil { w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Depth header is set to incorrect value %v", dh) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(log, w, b, err) return nil } @@ -634,7 +634,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re case srcStatRes.Status.Code == rpc.Code_CODE_NOT_FOUND: errors.HandleErrorStatus(log, w, srcStatRes.Status) m := fmt.Sprintf("Resource %v not found", srcStatReq.Ref.Path) - b, err := errors.Marshal(http.StatusNotFound, m, "") + b, err := errors.Marshal(http.StatusNotFound, m, "", "") errors.HandleWebdavError(log, w, b, err) return nil case srcStatRes.Status.Code != rpc.Code_CODE_OK: @@ -672,7 +672,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re log.Warn().Bool("overwrite", overwrite).Msg("dst already exists") w.WriteHeader(http.StatusPreconditionFailed) m := fmt.Sprintf("Could not overwrite Resource %v", dstRef.Path) - b, err := errors.Marshal(http.StatusPreconditionFailed, m, "") + b, err := errors.Marshal(http.StatusPreconditionFailed, m, "", "") errors.HandleWebdavError(log, w, b, err) // 412, see https://tools.ietf.org/html/rfc4918#section-9.8.5 return nil } diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index d6234f1508..50fe001667 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -52,6 +52,14 @@ const ( WwwAuthenticate = "Www-Authenticate" ) +const ( + ErrListingMembers = "ERR_LISTING_MEMBERS_NOT_ALLOWED" + ErrInvalidCredentials = "ERR_INVALID_CREDENTIALS" + ErrMissingBasicAuth = "ERR_MISSING_BASIC_AUTH" + ErrMissingBearerAuth = "ERR_MISSING_BEARER_AUTH" + ErrFileNotFoundInRoot = "ERR_FILE_NOT_FOUND_IN_ROOT" +) + // DavHandler routes to the different sub handlers type DavHandler struct { AvatarsHandler *AvatarsHandler @@ -132,7 +140,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler { if r.Header.Get(net.HeaderDepth) == "" { w.WriteHeader(http.StatusMethodNotAllowed) - b, err := errors.Marshal(http.StatusMethodNotAllowed, "Listing members of this collection is disabled", "") + b, err := errors.Marshal(http.StatusMethodNotAllowed, "Listing members of this collection is disabled", "", ErrListingMembers) if err != nil { log.Error().Msgf("error marshaling xml response: %s", b) w.WriteHeader(http.StatusInternalServerError) @@ -312,11 +320,11 @@ func (h *DavHandler) Handler(s *svc) http.Handler { case res.Status.Code == rpc.Code_CODE_UNAUTHENTICATED: w.WriteHeader(http.StatusUnauthorized) if hasValidBasicAuthHeader { - b, err := errors.Marshal(http.StatusUnauthorized, "Username or password was incorrect", "") + b, err := errors.Marshal(http.StatusUnauthorized, "Username or password was incorrect", "", ErrInvalidCredentials) errors.HandleWebdavError(log, w, b, err) return } - b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Basic' header found", "") + b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Basic' header found", "", ErrMissingBasicAuth) errors.HandleWebdavError(log, w, b, err) return case res.Status.Code == rpc.Code_CODE_NOT_FOUND: @@ -358,7 +366,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler { if !userExists { w.Header().Add(WwwAuthenticate, fmt.Sprintf("Bearer realm=\"%s\", charset=\"UTF-8\"", r.Host)) w.WriteHeader(http.StatusUnauthorized) - b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Bearer' header found", "") + b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Bearer' header found", "", ErrMissingBearerAuth) errors.HandleWebdavError(log, w, b, err) return } @@ -388,7 +396,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler { default: w.WriteHeader(http.StatusNotFound) - b, err := errors.Marshal(http.StatusNotFound, "File not found in root", "") + b, err := errors.Marshal(http.StatusNotFound, "File not found in root", "", ErrFileNotFoundInRoot) errors.HandleWebdavError(log, w, b, err) } }) diff --git a/internal/http/services/owncloud/ocdav/errors/error.go b/internal/http/services/owncloud/ocdav/errors/error.go index adf55e589c..2709eb5ca3 100644 --- a/internal/http/services/owncloud/ocdav/errors/error.go +++ b/internal/http/services/owncloud/ocdav/errors/error.go @@ -101,13 +101,14 @@ type Exception struct { } // Marshal just calls the xml marshaller for a given exception. -func Marshal(code int, message string, header string) ([]byte, error) { +func Marshal(code int, message string, header string, errorCode string) ([]byte, error) { xmlstring, err := xml.Marshal(&ErrorXML{ Xmlnsd: "DAV", Xmlnss: "http://sabredav.org/ns", Exception: sabreException[code], Message: message, Header: header, + ErrorCode: errorCode, }) if err != nil { return nil, err @@ -126,6 +127,7 @@ type ErrorXML struct { Xmlnss string `xml:"xmlns:s,attr"` Exception string `xml:"s:exception"` Message string `xml:"s:message"` + ErrorCode string `xml:"s:errorcode"` InnerXML []byte `xml:",innerxml"` // Header is used to indicate the conflicting request header Header string `xml:"s:header,omitempty"` diff --git a/internal/http/services/owncloud/ocdav/meta.go b/internal/http/services/owncloud/ocdav/meta.go index 9cd939057e..9bdf2a99e9 100644 --- a/internal/http/services/owncloud/ocdav/meta.go +++ b/internal/http/services/owncloud/ocdav/meta.go @@ -68,7 +68,7 @@ func (h *MetaHandler) Handler(s *svc) http.Handler { logger.Debug().Str("prop", net.PropOcMetaPathForUser).Msg("invalid resource id") w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid resource id %v", id) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(logger, w, b, err) return } @@ -139,7 +139,7 @@ func (h *MetaHandler) handlePathForUser(w http.ResponseWriter, r *http.Request, sublog.Debug().Str("code", string(pathRes.Status.Code)).Msg("resource not found") w.WriteHeader(http.StatusNotFound) m := fmt.Sprintf("Resource %s not found", id) - b, err := errors.Marshal(http.StatusNotFound, m, "") + b, err := errors.Marshal(http.StatusNotFound, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return case rpc.Code_CODE_PERMISSION_DENIED: @@ -147,7 +147,7 @@ func (h *MetaHandler) handlePathForUser(w http.ResponseWriter, r *http.Request, sublog.Debug().Str("code", string(pathRes.Status.Code)).Msg("resource access denied") w.WriteHeader(http.StatusNotFound) m := fmt.Sprintf("Resource %s not found", id) - b, err := errors.Marshal(http.StatusNotFound, m, "") + b, err := errors.Marshal(http.StatusNotFound, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } diff --git a/internal/http/services/owncloud/ocdav/move.go b/internal/http/services/owncloud/ocdav/move.go index d3307f1042..3e1f587282 100644 --- a/internal/http/services/owncloud/ocdav/move.go +++ b/internal/http/services/owncloud/ocdav/move.go @@ -44,7 +44,7 @@ func (s *svc) handlePathMove(w http.ResponseWriter, r *http.Request, ns string) if r.Body != http.NoBody { w.WriteHeader(http.StatusUnsupportedMediaType) - b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "") + b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } @@ -55,21 +55,21 @@ func (s *svc) handlePathMove(w http.ResponseWriter, r *http.Request, ns string) dstPath, err := net.ParseDestination(baseURI, dh) if err != nil { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, "failed to extract destination", "") + b, err := errors.Marshal(http.StatusBadRequest, "failed to extract destination", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } if err := ValidateName(filename(srcPath), s.nameValidators); err != nil { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, "source failed naming rules", "") + b, err := errors.Marshal(http.StatusBadRequest, "source failed naming rules", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } if err := ValidateDestination(filename(dstPath), s.nameValidators); err != nil { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, "destination naming rules", "") + b, err := errors.Marshal(http.StatusBadRequest, "destination naming rules", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } @@ -108,7 +108,7 @@ func (s *svc) handleSpacesMove(w http.ResponseWriter, r *http.Request, srcSpaceI if r.Body != http.NoBody { w.WriteHeader(http.StatusUnsupportedMediaType) - b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "") + b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "", "") errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } @@ -157,7 +157,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req } if isChild { w.WriteHeader(http.StatusConflict) - b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into one of its children", "") + b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into one of its children", "", "") errors.HandleWebdavError(&log, w, b, err) return } @@ -179,7 +179,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req } if isParent { w.WriteHeader(http.StatusConflict) - b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into its parent", "") + b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into its parent", "", "") errors.HandleWebdavError(&log, w, b, err) return @@ -213,7 +213,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req if srcStatRes.Status.Code == rpc.Code_CODE_NOT_FOUND { w.WriteHeader(http.StatusNotFound) m := fmt.Sprintf("Resource %v not found", srcStatReq.Ref.Path) - b, err := errors.Marshal(http.StatusNotFound, m, "") + b, err := errors.Marshal(http.StatusNotFound, m, "", "") errors.HandleWebdavError(&log, w, b, err) } errors.HandleErrorStatus(&log, w, srcStatRes.Status) @@ -321,7 +321,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req w.WriteHeader(status) - b, err := errors.Marshal(status, m, "") + b, err := errors.Marshal(status, m, "", "") errors.HandleWebdavError(&log, w, b, err) return } diff --git a/internal/http/services/owncloud/ocdav/ocdav_blackbox_test.go b/internal/http/services/owncloud/ocdav/ocdav_blackbox_test.go index 008f3ebd80..bbfce7cded 100644 --- a/internal/http/services/owncloud/ocdav/ocdav_blackbox_test.go +++ b/internal/http/services/owncloud/ocdav/ocdav_blackbox_test.go @@ -493,7 +493,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(http.StatusNotFound)) - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") }) }) @@ -1098,7 +1098,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(http.StatusMethodNotAllowed)) - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\MethodNotAlloweddeleting spaces via dav is not allowed"), "Body must have a sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\MethodNotAlloweddeleting spaces via dav is not allowed"), "Body must have a sabredav exception") }) It("with invalid if header return bad request status", func() { rr := httptest.NewRecorder() @@ -1121,7 +1121,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(http.StatusUnsupportedMediaType)) - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\UnsupportedMediaTypebody must be empty"), "Body must have a sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\UnsupportedMediaTypebody must be empty"), "Body must have a sabredav exception") }, Entry("MOVE", "MOVE", "/webdav/source"), Entry("COPY", "COPY", "/webdav/source"), @@ -1220,7 +1220,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(expectedStatus)) if expectedStatus == http.StatusInternalServerError { - Expect(rr).To(HaveHTTPBody("\nunexpected io error"), "Body must have a sabredav exception") + Expect(rr).To(HaveHTTPBody("\nunexpected io error"), "Body must have a sabredav exception") } else { Expect(rr).To(HaveHTTPBody(""), "Body must be empty") } @@ -1262,7 +1262,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(expectedStatus)) if expectedStatus == http.StatusInternalServerError { - Expect(rr).To(HaveHTTPBody("\nunexpected io error"), "Body must have a sabredav exception") + Expect(rr).To(HaveHTTPBody("\nunexpected io error"), "Body must have a sabredav exception") } else { Expect(rr).To(HaveHTTPBody(""), "Body must be empty") } @@ -1306,7 +1306,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(expectedStatus)) if expectedStatus == http.StatusInternalServerError { - Expect(rr).To(HaveHTTPBody("\nunexpected io error"), "Body must have a sabredav exception") + Expect(rr).To(HaveHTTPBody("\nunexpected io error"), "Body must have a sabredav exception") } else { Expect(rr).To(HaveHTTPBody(""), "Body must be empty") } @@ -1350,7 +1350,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(expectedStatus)) if expectedStatus == http.StatusInternalServerError { - Expect(rr).To(HaveHTTPBody("\nunexpected io error"), "Body must have a sabredav exception") + Expect(rr).To(HaveHTTPBody("\nunexpected io error"), "Body must have a sabredav exception") } else { Expect(rr).To(HaveHTTPBody(""), "Body must be empty") } @@ -1482,7 +1482,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(expectedStatus)) if expectedStatus == http.StatusNotFound { - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") } else { Expect(rr).To(HaveHTTPBody(""), "Body must be empty") } @@ -1527,7 +1527,7 @@ var _ = Describe("ocdav", func() { handler.Handler().ServeHTTP(rr, req) Expect(rr).To(HaveHTTPStatus(expectedStatus)) if expectedStatus == http.StatusNotFound { - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") } else { Expect(rr).To(HaveHTTPBody(""), "Body must be empty") } @@ -1594,13 +1594,13 @@ var _ = Describe("ocdav", func() { } else { if userHasAccess { if locked { - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\Locked"), "Body must have a locked sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\Locked"), "Body must have a locked sabredav exception") Expect(rr).To(HaveHTTPHeaderWithValue("Lock-Token", "")) } else { - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\Forbidden"), "Body must have a forbidden sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\Forbidden"), "Body must have a forbidden sabredav exception") } } else { - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") } } }, @@ -1695,13 +1695,13 @@ var _ = Describe("ocdav", func() { } else { if userHasAccess { if locked { - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\Locked"), "Body must have a locked sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\Locked"), "Body must have a locked sabredav exception") Expect(rr).To(HaveHTTPHeaderWithValue("Lock-Token", "")) } else { - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\Forbidden"), "Body must have a forbidden sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\Forbidden"), "Body must have a forbidden sabredav exception") } } else { - Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") + Expect(rr).To(HaveHTTPBody("\nSabre\\DAV\\Exception\\NotFoundResource not found"), "Body must have a not found sabredav exception") } } }, diff --git a/internal/http/services/owncloud/ocdav/propfind/propfind.go b/internal/http/services/owncloud/ocdav/propfind/propfind.go index b2cb26113e..31f11b6ebc 100644 --- a/internal/http/services/owncloud/ocdav/propfind/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind/propfind.go @@ -243,7 +243,7 @@ func (p *Handler) HandlePathPropfind(w http.ResponseWriter, r *http.Request, ns sublog.Debug().Str("depth", dh).Msg(err.Error()) w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid Depth header value: %v", dh) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -255,7 +255,7 @@ func (p *Handler) HandlePathPropfind(w http.ResponseWriter, r *http.Request, ns sublog.Debug().Str("depth", dh).Msg(errors.ErrInvalidDepth.Error()) w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid Depth header value: %v", dh) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -312,7 +312,7 @@ func (p *Handler) HandleSpacesPropfind(w http.ResponseWriter, r *http.Request, s sublog.Debug().Str("depth", dh).Msg(err.Error()) w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid Depth header value: %v", dh) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -324,7 +324,7 @@ func (p *Handler) HandleSpacesPropfind(w http.ResponseWriter, r *http.Request, s sublog.Debug().Str("depth", dh).Msg(errors.ErrInvalidDepth.Error()) w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid Depth header value: %v", dh) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -341,7 +341,7 @@ func (p *Handler) HandleSpacesPropfind(w http.ResponseWriter, r *http.Request, s sublog.Debug().Msg("invalid space id") w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid space id: %v", spaceID) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -391,7 +391,7 @@ func (p *Handler) HandleSpacesPropfind(w http.ResponseWriter, r *http.Request, s m = "Resource not found" // mimic the oc10 error message } w.WriteHeader(status) - b, err := errors.Marshal(status, m, "") + b, err := errors.Marshal(status, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -618,7 +618,7 @@ func (p *Handler) getResourceInfos(ctx context.Context, w http.ResponseWriter, r // TODO if we have children invent node on the fly w.WriteHeader(http.StatusNotFound) m := "Resource not found" - b, err := errors.Marshal(http.StatusNotFound, m, "") + b, err := errors.Marshal(http.StatusNotFound, m, "", "") errors.HandleWebdavError(&log, w, b, err) return nil, false, false } diff --git a/internal/http/services/owncloud/ocdav/proppatch.go b/internal/http/services/owncloud/ocdav/proppatch.go index 9c920c170b..6ead723f5e 100644 --- a/internal/http/services/owncloud/ocdav/proppatch.go +++ b/internal/http/services/owncloud/ocdav/proppatch.go @@ -208,7 +208,7 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt m = "Resource not found" // mimic the oc10 error message } w.WriteHeader(status) - b, err := errors.Marshal(status, m, "") + b, err := errors.Marshal(status, m, "", "") errors.HandleWebdavError(&log, w, b, err) return nil, nil, false } @@ -273,7 +273,7 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt m = "Resource not found" // mimic the oc10 error message } w.WriteHeader(status) - b, err := errors.Marshal(status, m, "") + b, err := errors.Marshal(status, m, "", "") errors.HandleWebdavError(&log, w, b, err) return nil, nil, false } diff --git a/internal/http/services/owncloud/ocdav/publicfile.go b/internal/http/services/owncloud/ocdav/publicfile.go index 91bfe5f1b4..f44a67e6b6 100644 --- a/internal/http/services/owncloud/ocdav/publicfile.go +++ b/internal/http/services/owncloud/ocdav/publicfile.go @@ -102,7 +102,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s span.SetStatus(codes.Error, ocdaverrors.ErrTokenStatInfoMissing.Error()) span.SetAttributes(semconv.HTTPStatusCodeKey.Int(http.StatusInternalServerError)) w.WriteHeader(http.StatusInternalServerError) - b, err := ocdaverrors.Marshal(http.StatusInternalServerError, ocdaverrors.ErrTokenStatInfoMissing.Error(), "") + b, err := ocdaverrors.Marshal(http.StatusInternalServerError, ocdaverrors.ErrTokenStatInfoMissing.Error(), "", "") ocdaverrors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err) return } @@ -118,7 +118,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s sublog.Debug().Str("depth", dh).Msg(err.Error()) w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid Depth header value: %v", dh) - b, err := ocdaverrors.Marshal(http.StatusBadRequest, m, "") + b, err := ocdaverrors.Marshal(http.StatusBadRequest, m, "", "") ocdaverrors.HandleWebdavError(&sublog, w, b, err) return } @@ -130,7 +130,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s sublog.Debug().Str("depth", dh).Msg(ocdaverrors.ErrInvalidDepth.Error()) w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid Depth header value: %v", dh) - b, err := ocdaverrors.Marshal(http.StatusBadRequest, m, "") + b, err := ocdaverrors.Marshal(http.StatusBadRequest, m, "", "") ocdaverrors.HandleWebdavError(&sublog, w, b, err) return } diff --git a/internal/http/services/owncloud/ocdav/put.go b/internal/http/services/owncloud/ocdav/put.go index 9619461e4e..8246b76f22 100644 --- a/internal/http/services/owncloud/ocdav/put.go +++ b/internal/http/services/owncloud/ocdav/put.go @@ -117,7 +117,7 @@ func (s *svc) handlePathPut(w http.ResponseWriter, r *http.Request, ns string) { if err := ValidateName(filename(r.URL.Path), s.nameValidators); err != nil { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "") + b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -318,7 +318,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ m = "Resource not found" // mimic the oc10 error message } w.WriteHeader(status) - b, err := errors.Marshal(status, m, "") + b, err := errors.Marshal(status, m, "", "") errors.HandleWebdavError(&log, w, b, err) case rpc.Code_CODE_ABORTED: w.WriteHeader(http.StatusPreconditionFailed) @@ -364,7 +364,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ } if httpRes.StatusCode == errtypes.StatusChecksumMismatch { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, "The computed checksum does not match the one received from the client.", "") + b, err := errors.Marshal(http.StatusBadRequest, "The computed checksum does not match the one received from the client.", "", "") errors.HandleWebdavError(&log, w, b, err) return } @@ -413,7 +413,7 @@ func (s *svc) handleSpacesPut(w http.ResponseWriter, r *http.Request, spaceID st if err := ValidateName(filename(ref.Path), s.nameValidators); err != nil { w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "") + b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "", "") errors.HandleWebdavError(&sublog, w, b, err) return } diff --git a/internal/http/services/owncloud/ocdav/spaces.go b/internal/http/services/owncloud/ocdav/spaces.go index e8706becff..158fc569b6 100644 --- a/internal/http/services/owncloud/ocdav/spaces.go +++ b/internal/http/services/owncloud/ocdav/spaces.go @@ -115,7 +115,7 @@ func (h *SpacesHandler) Handler(s *svc, trashbinHandler *TrashbinHandler) http.H w.WriteHeader(status) if status != http.StatusNoContent { var b []byte - if b, err = errors.Marshal(status, err.Error(), ""); err == nil { + if b, err = errors.Marshal(status, err.Error(), "", ""); err == nil { _, err = w.Write(b) } } diff --git a/internal/http/services/owncloud/ocdav/tpc.go b/internal/http/services/owncloud/ocdav/tpc.go index 0c18979f80..6205a7be30 100644 --- a/internal/http/services/owncloud/ocdav/tpc.go +++ b/internal/http/services/owncloud/ocdav/tpc.go @@ -129,7 +129,7 @@ func (s *svc) handleTPCPull(ctx context.Context, w http.ResponseWriter, r *http. w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Overwrite header is set to incorrect value %v", overwrite) sublog.Warn().Msgf("HTTP TPC Pull: %s", m) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -293,7 +293,7 @@ func (s *svc) handleTPCPush(ctx context.Context, w http.ResponseWriter, r *http. w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Overwrite header is set to incorrect value %v", overwrite) sublog.Warn().Msgf("HTTP TPC Push: %s", m) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go index 51205a3a05..0888151f95 100644 --- a/internal/http/services/owncloud/ocdav/trashbin.go +++ b/internal/http/services/owncloud/ocdav/trashbin.go @@ -91,7 +91,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { // listing other users trash is forbidden, no auth will change that // do not leak existence of space and return 404 w.WriteHeader(http.StatusNotFound) - b, err := errors.Marshal(http.StatusNotFound, "not found", "") + b, err := errors.Marshal(http.StatusNotFound, "not found", "", "") if err != nil { log.Error().Msgf("error marshaling xml response: %s", b) w.WriteHeader(http.StatusInternalServerError) @@ -110,7 +110,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { ns, newPath, err := s.ApplyLayout(ctx, h.namespace, useLoggedInUser, r.URL.Path) if err != nil { w.WriteHeader(http.StatusNotFound) - b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "") + b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "", "") errors.HandleWebdavError(appctx.GetLogger(r.Context()), w, b, err) } r.URL.Path = newPath @@ -125,7 +125,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { case rpcstatus.Code != rpc.Code_CODE_OK: httpStatus := rstatus.HTTPStatusFromCode(rpcstatus.Code) w.WriteHeader(httpStatus) - b, err := errors.Marshal(httpStatus, rpcstatus.Message, "") + b, err := errors.Marshal(httpStatus, rpcstatus.Message, "", "") errors.HandleWebdavError(log, w, b, err) return } @@ -165,7 +165,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { if rpcstatus.Code != rpc.Code_CODE_OK { httpStatus := rstatus.HTTPStatusFromCode(rpcstatus.Code) w.WriteHeader(httpStatus) - b, err := errors.Marshal(httpStatus, rpcstatus.Message, "") + b, err := errors.Marshal(httpStatus, rpcstatus.Message, "", "") errors.HandleWebdavError(log, w, b, err) return } @@ -196,7 +196,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s sublog.Debug().Str("depth", dh).Msg(err.Error()) w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid Depth header value: %v", dh) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -208,7 +208,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s sublog.Debug().Str("depth", dh).Msg(errors.ErrInvalidDepth.Error()) w.WriteHeader(http.StatusBadRequest) m := fmt.Sprintf("Invalid Depth header value: %v", dh) - b, err := errors.Marshal(http.StatusBadRequest, m, "") + b, err := errors.Marshal(http.StatusBadRequest, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -256,7 +256,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s if getRecycleRes.Status.Code != rpc.Code_CODE_OK { httpStatus := rstatus.HTTPStatusFromCode(getRecycleRes.Status.Code) w.WriteHeader(httpStatus) - b, err := errors.Marshal(httpStatus, getRecycleRes.Status.Message, "") + b, err := errors.Marshal(httpStatus, getRecycleRes.Status.Message, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -286,7 +286,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s if getRecycleRes.Status.Code != rpc.Code_CODE_OK { httpStatus := rstatus.HTTPStatusFromCode(getRecycleRes.Status.Code) w.WriteHeader(httpStatus) - b, err := errors.Marshal(httpStatus, getRecycleRes.Status.Message, "") + b, err := errors.Marshal(httpStatus, getRecycleRes.Status.Message, "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -544,6 +544,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc http.StatusPreconditionFailed, "The destination node already exists, and the overwrite header is set to false", net.HeaderOverwrite, + "", ) errors.HandleWebdavError(&sublog, w, b, err) return @@ -579,7 +580,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc if res.Status.Code != rpc.Code_CODE_OK { if res.Status.Code == rpc.Code_CODE_PERMISSION_DENIED { w.WriteHeader(http.StatusForbidden) - b, err := errors.Marshal(http.StatusForbidden, "Permission denied to restore", "") + b, err := errors.Marshal(http.StatusForbidden, "Permission denied to restore", "", "") errors.HandleWebdavError(&sublog, w, b, err) } errors.HandleErrorStatus(&sublog, w, res.Status) @@ -638,7 +639,7 @@ func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc, sublog.Debug().Interface("status", res.Status).Msg("resource not found") w.WriteHeader(http.StatusConflict) m := fmt.Sprintf("path %s not found", trashPath) - b, err := errors.Marshal(http.StatusConflict, m, "") + b, err := errors.Marshal(http.StatusConflict, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) case rpc.Code_CODE_PERMISSION_DENIED: w.WriteHeader(http.StatusForbidden) @@ -648,7 +649,7 @@ func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc, } else { m = "Permission denied to delete" } - b, err := errors.Marshal(http.StatusForbidden, m, "") + b, err := errors.Marshal(http.StatusForbidden, m, "", "") errors.HandleWebdavError(&sublog, w, b, err) default: errors.HandleErrorStatus(&sublog, w, res.Status) diff --git a/internal/http/services/owncloud/ocdav/versions.go b/internal/http/services/owncloud/ocdav/versions.go index 1f6099597d..0c9de36c35 100644 --- a/internal/http/services/owncloud/ocdav/versions.go +++ b/internal/http/services/owncloud/ocdav/versions.go @@ -139,7 +139,7 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, if res.Status.Code != rpc.Code_CODE_OK { if res.Status.Code == rpc.Code_CODE_PERMISSION_DENIED || res.Status.Code == rpc.Code_CODE_NOT_FOUND { w.WriteHeader(http.StatusNotFound) - b, err := errors.Marshal(http.StatusNotFound, "Resource not found", "") + b, err := errors.Marshal(http.StatusNotFound, "Resource not found", "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -158,7 +158,7 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, if lvRes.Status.Code != rpc.Code_CODE_OK { if lvRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED { w.WriteHeader(http.StatusForbidden) - b, err := errors.Marshal(http.StatusForbidden, "You have no permission to list file versions on this resource", "") + b, err := errors.Marshal(http.StatusForbidden, "You have no permission to list file versions on this resource", "", "") errors.HandleWebdavError(&sublog, w, b, err) return } @@ -247,7 +247,7 @@ func (h *VersionsHandler) doRestore(w http.ResponseWriter, r *http.Request, s *s if res.Status.Code != rpc.Code_CODE_OK { if res.Status.Code == rpc.Code_CODE_PERMISSION_DENIED { w.WriteHeader(http.StatusForbidden) - b, err := errors.Marshal(http.StatusForbidden, "You have no permission to restore versions on this resource", "") + b, err := errors.Marshal(http.StatusForbidden, "You have no permission to restore versions on this resource", "", "") errors.HandleWebdavError(&sublog, w, b, err) return } diff --git a/internal/http/services/owncloud/ocdav/webdav.go b/internal/http/services/owncloud/ocdav/webdav.go index 3a50b760a3..e2f6b96c25 100644 --- a/internal/http/services/owncloud/ocdav/webdav.go +++ b/internal/http/services/owncloud/ocdav/webdav.go @@ -61,7 +61,7 @@ func (h *WebDavHandler) Handler(s *svc) http.Handler { ns, newPath, err := s.ApplyLayout(r.Context(), h.namespace, h.useLoggedInUserNS, r.URL.Path) if err != nil { w.WriteHeader(http.StatusNotFound) - b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "") + b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "", "") errors.HandleWebdavError(appctx.GetLogger(r.Context()), w, b, err) return } @@ -108,7 +108,7 @@ func (h *WebDavHandler) Handler(s *svc) http.Handler { w.WriteHeader(status) if status != http.StatusNoContent { var b []byte - if b, err = errors.Marshal(status, err.Error(), ""); err == nil { + if b, err = errors.Marshal(status, err.Error(), "", ""); err == nil { _, err = w.Write(b) } }