You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	API: Allow specifying item ID for any item
This commit is contained in:
		| @@ -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" }); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user