From 49f8d0c6d890b39a24979df0864d579059828e20 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Wed, 6 Feb 2019 22:36:39 +0000 Subject: [PATCH] API: Allow specifying item ID for any item --- CliClient/tests/services_rest_Api.js | 11 ++++++++ ReactNativeClient/lib/ClipperServer.js | 2 +- ReactNativeClient/lib/services/rest/Api.js | 31 ++++++++++++++-------- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/CliClient/tests/services_rest_Api.js b/CliClient/tests/services_rest_Api.js index 1515d40729..6e985c2b9b 100644 --- a/CliClient/tests/services_rest_Api.js +++ b/CliClient/tests/services_rest_Api.js @@ -170,6 +170,17 @@ describe('services_rest_Api', function() { done(); }); + it('should create folders with supplied ID', async (done) => { + const response = await api.route('POST', 'folders', null, JSON.stringify({ + id: '12345678123456781234567812345678', + title: 'from api', + })); + + expect(response.id).toBe('12345678123456781234567812345678'); + + done(); + }); + it('should create notes with images', async (done) => { let response = null; const f = await Folder.save({ title: "mon carnet" }); diff --git a/ReactNativeClient/lib/ClipperServer.js b/ReactNativeClient/lib/ClipperServer.js index d7c1e5c940..cc2a5d6707 100644 --- a/ReactNativeClient/lib/ClipperServer.js +++ b/ReactNativeClient/lib/ClipperServer.js @@ -145,7 +145,7 @@ class ClipperServer { const execRequest = async (request, body = '', files = []) => { try { const response = await this.api_.route(request.method, url.pathname, url.query, body, files); - writeResponse(200, response); + writeResponse(200, response ? response : ''); } catch (error) { this.logger().error(error); writeResponse(error.httpCode ? error.httpCode : 500, error.message); diff --git a/ReactNativeClient/lib/services/rest/Api.js b/ReactNativeClient/lib/services/rest/Api.js index 176b01c6a2..28dec68b31 100644 --- a/ReactNativeClient/lib/services/rest/Api.js +++ b/ReactNativeClient/lib/services/rest/Api.js @@ -103,7 +103,7 @@ class Api { if (!this[parsedPath.callName]) throw new ErrorNotFound(); try { - return this[parsedPath.callName](request, id, link); + return await this[parsedPath.callName](request, id, link); } catch (error) { if (!error.httpCode) error.httpCode = 500; throw error; @@ -118,8 +118,10 @@ class Api { return this.logger_; } - get readonlyProperties() { - return ['id', 'created_time', 'updated_time', 'encryption_blob_encrypted', 'encryption_applied', 'encryption_cipher_text']; + readonlyProperties(requestMethod) { + const output = ['created_time', 'updated_time', 'encryption_blob_encrypted', 'encryption_applied', 'encryption_cipher_text']; + if (requestMethod !== 'POST') output.splice(0, 0, 'id'); + return output; } fields_(request, defaultFields) { @@ -174,7 +176,7 @@ class Api { if (request.method === 'PUT' && id) { const model = await getOneModel(); - let newModel = Object.assign({}, model, request.bodyJson(this.readonlyProperties)); + let newModel = Object.assign({}, model, request.bodyJson(this.readonlyProperties('PUT'))); newModel = await ModelClass.save(newModel, { userSideValidation: true }); return newModel; } @@ -186,8 +188,11 @@ class Api { } if (request.method === 'POST') { - const model = request.bodyJson(this.readonlyProperties); - const result = await ModelClass.save(model, { userSideValidation: true }); + const props = this.readonlyProperties('POST'); + const idIdx = props.indexOf('id'); + if (idIdx >= 0) props.splice(idIdx, 1); + const model = request.bodyJson(props); + const result = await ModelClass.save(model, this.defaultSaveOptions_(model, 'POST')); return result; } @@ -286,9 +291,8 @@ class Api { if (request.method === 'POST') { if (!request.files.length) throw new ErrorBadRequest('Resource cannot be created without a file'); const filePath = request.files[0].path; - const resource = await shim.createResourceFromPath(filePath); - const newResource = Object.assign({}, resource, request.bodyJson(this.readonlyProperties)); - return await Resource.save(newResource); + const defaultProps = request.bodyJson(this.readonlyProperties('POST')); + return shim.createResourceFromPath(filePath, defaultProps); } return this.defaultAction_(BaseModel.TYPE_RESOURCE, request, id, link); @@ -301,6 +305,12 @@ class Api { return options; } + defaultSaveOptions_(model, requestMethod) { + const options = { userSideValidation: true }; + if (requestMethod === 'POST' && model.id) options.isNew = true; + return options; + } + async action_notes(request, id = null, link = null) { this.checkToken_(request); @@ -342,8 +352,7 @@ class Api { this.logger().info('Request (' + requestId + '): Saving note...'); - const saveOptions = {}; - if (note.id) saveOptions.isNew = true; + const saveOptions = this.defaultSaveOptions_(note, 'POST'); note = await Note.save(note, saveOptions); if (requestNote.tags) {