From 3feef922540a6c2c9163da78c0bddb0e98cb1c9b Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 4 Aug 2017 16:50:58 +0200 Subject: [PATCH] Detect PROPPATCH failure by parsing multistatus PROPPATCH might fail but the HTTP status is still 207. Need to check the propstat of the response to find the actual error codes. If an error is found, it now calls the error callback instead and uses the 422 status code "Unprocessable Entity" to match the way REST works for server side validation. --- core/js/oc-backbone-webdav.js | 10 +++ core/js/tests/specs/oc-backbone-webdavSpec.js | 65 ++++++++++++++++++- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/core/js/oc-backbone-webdav.js b/core/js/oc-backbone-webdav.js index 435d7dc46441..724660ff93a2 100644 --- a/core/js/oc-backbone-webdav.js +++ b/core/js/oc-backbone-webdav.js @@ -185,6 +185,16 @@ convertModelAttributesToDavProperties(model.changed, options.davProperties), headers ).then(function(result) { + if (result.status === 207 && result.body && result.body.length > 0) { + if (_.find(result.body[0].propStat, function(propStat) { + var statusCode = parseInt(propStat.status.split(' ')[1], 10); + return statusCode >= 400; + })) { + // in REST, validation errors are usually represented with 422 Unprocessable Entity, + result.status = 422; + } + } + if (isSuccessStatus(result.status)) { if (_.isFunction(options.success)) { // pass the object's own values because the server diff --git a/core/js/tests/specs/oc-backbone-webdavSpec.js b/core/js/tests/specs/oc-backbone-webdavSpec.js index 86dde92c2be8..6df6da4e6161 100644 --- a/core/js/tests/specs/oc-backbone-webdavSpec.js +++ b/core/js/tests/specs/oc-backbone-webdavSpec.js @@ -271,8 +271,18 @@ describe('Backbone Webdav extension', function() { .toEqual('XMLHttpRequest'); deferredRequest.resolve({ - status: 201, - body: '' + status: 207, + body: [{ + href: 'http://example.com/owncloud/remote.php/test/123', + propStat: [{ + status: 'HTTP/1.1 200 OK', + properties: { + '{http://owncloud.org/ns}first-name': '', + '{http://owncloud.org/ns}age-name': '', + '{http://owncloud.org/ns}married': '' + } + }] + }] }); expect(model.id).toEqual('123'); @@ -281,6 +291,51 @@ describe('Backbone Webdav extension', function() { expect(model.get('married')).toEqual(true); }); + it('calls error callback with status code 422 in case of failed PROPPATCH properties', function() { + var successHandler = sinon.stub(); + var errorHandler = sinon.stub(); + var model = new TestModel({ + id: '123', + firstName: 'Hello', + lastName: 'World', + age: 32, + married: false + }); + + model.save({ + firstName: 'Hey', + lastName: 'low' + }, { + success: successHandler, + error: errorHandler + }); + + deferredRequest.resolve({ + status: 207, + body: [{ + href: 'http://example.com/owncloud/remote.php/test/123', + propStat: [{ + status: 'HTTP/1.1 200 OK', + properties: { + '{http://owncloud.org/ns}last-name': '' + } + }, { + status: 'HTTP/1.1 403 Forbidden', + properties: { + '{http://owncloud.org/ns}first-name': '' + } + }] + }] + }); + + expect(davClientPropPatchStub.calledOnce).toEqual(true); + + expect(successHandler.notCalled).toEqual(true); + expect(errorHandler.calledOnce).toEqual(true); + expect(errorHandler.getCall(0).args[0]).toEqual(model); + expect(errorHandler.getCall(0).args[1].status).toEqual(422); + }); + it('uses PROPFIND to fetch single model', function() { var model = new TestModel({ id: '123' @@ -774,7 +829,11 @@ describe('Backbone Webdav extension', function() { deferredRequest.resolve({ status: 201, - body: '', + body: [{ + propStat: { + status: 'HTTP/1.1 200 OK' + } + }], xhr: { getResponseHeader: _.noop }