From d5fd15224ec1e6d0f9c8cd33c1f91f861fba1740 Mon Sep 17 00:00:00 2001 From: joan Date: Wed, 29 Mar 2023 14:57:14 +0200 Subject: [PATCH] fix(sqlConnector): handled malformed json parse Refs #4862 --- loopback/server/connectors/vn-mysql.js | 119 +++++++++++++++---------- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/loopback/server/connectors/vn-mysql.js b/loopback/server/connectors/vn-mysql.js index 5c1ceaa32..728454d86 100644 --- a/loopback/server/connectors/vn-mysql.js +++ b/loopback/server/connectors/vn-mysql.js @@ -1,8 +1,7 @@ const mysql = require('mysql'); -const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const MySQL = require('loopback-connector-mysql').MySQL; const EnumFactory = require('loopback-connector-mysql').EnumFactory; -const Transaction = require('loopback-connector').Transaction; +const { Transaction, SQLConnector, ParameterizedSQL } = require('loopback-connector'); const fs = require('fs'); const limitSet = new Set([ @@ -254,49 +253,49 @@ class VnMySQL extends MySQL { } create(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('create', arguments, model, ctx, opts, cb); } createAll(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('createAll', arguments, model, ctx, opts, cb); } save(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('save', arguments, model, ctx, opts, cb); } updateOrCreate(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('updateOrCreate', arguments, model, ctx, opts, cb); } replaceOrCreate(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('replaceOrCreate', arguments, model, ctx, opts, cb); } destroyAll(model, where, opts, cb) { - const ctx = {where}; + const ctx = { where }; this.invokeMethod('destroyAll', arguments, model, ctx, opts, cb); } update(model, where, data, opts, cb) { - const ctx = {where, data}; + const ctx = { where, data }; this.invokeMethod('update', arguments, model, ctx, opts, cb); } replaceById(model, id, data, opts, cb) { - const ctx = {id, data}; + const ctx = { id, data }; this.invokeMethod('replaceById', arguments, model, ctx, opts, cb); } @@ -321,16 +320,16 @@ class VnMySQL extends MySQL { let tx; if (!opts.transaction) { tx = await Transaction.begin(this, {}); - opts = Object.assign({transaction: tx, httpCtx: opts.httpCtx}, opts); + opts = Object.assign({ transaction: tx, httpCtx: opts.httpCtx }, opts); } try { // Fetch old values (update|delete) or login let where, id, data, idName, limit, op, oldInstances, newInstances; const hasGrabUser = settings.log && settings.log.grabUser; - if(hasGrabUser){ + if (hasGrabUser) { const userId = opts.httpCtx && opts.httpCtx.active.accessToken.userId; - const user = await Model.app.models.Account.findById(userId, {fields: ['name']}, opts); + const user = await Model.app.models.Account.findById(userId, { fields: ['name'] }, opts); await this.executeP(`CALL account.myUser_loginWithName(?)`, [user.name], opts); } else { @@ -344,18 +343,18 @@ class VnMySQL extends MySQL { op = opMap.get(method); if (!where) { - if (id) where = {[idName]: id}; - else where = {[idName]: data[idName]}; + if (id) where = { [idName]: id }; + else where = { [idName]: data[idName] }; } // Fetch old values switch (op) { - case 'update': - case 'delete': - // Single entity operation - const stmt = this.buildSelectStmt(op, data, idName, model, where, limit); - stmt.merge(`FOR UPDATE`); - oldInstances = await this.executeStmt(stmt, opts); + case 'update': + case 'delete': + // Single entity operation + const stmt = this.buildSelectStmt(op, data, idName, model, where, limit); + stmt.merge(`FOR UPDATE`); + oldInstances = await this.executeStmt(stmt, opts); } } @@ -365,30 +364,30 @@ class VnMySQL extends MySQL { super[method].apply(this, fnArgs); }); - if(hasGrabUser) + if (hasGrabUser) await this.executeP(`CALL account.myUser_logout()`, null, opts); else { // Fetch new values const ids = []; switch (op) { - case 'insert': - case 'update': { + case 'insert': + case 'update': { switch (method) { - case 'createAll': - for (const row of res[1]) - ids.push(row[idName]); - break; - case 'create': - ids.push(res[1]); - break; - case 'update': - if (data[idName] != null) - ids.push(data[idName]); - break; + case 'createAll': + for (const row of res[1]) + ids.push(row[idName]); + break; + case 'create': + ids.push(res[1]); + break; + case 'update': + if (data[idName] != null) + ids.push(data[idName]); + break; } - const newWhere = ids.length ? {[idName]: ids} : where; + const newWhere = ids.length ? { [idName]: ids } : where; const stmt = this.buildSelectStmt(op, data, idName, model, newWhere, limit); newInstances = await this.executeStmt(stmt, opts); @@ -431,9 +430,9 @@ class VnMySQL extends MySQL { const stmt = new ParameterizedSQL( 'SELECT ' + - this.buildColumnNames(model, {fields}) + - ' FROM ' + - this.tableEscaped(model) + this.buildColumnNames(model, { fields }) + + ' FROM ' + + this.tableEscaped(model) ); stmt.merge(this.buildWhere(model, where)); if (limit) stmt.merge(`LIMIT 1`); @@ -505,8 +504,8 @@ class VnMySQL extends MySQL { if (oldI) { Object.keys(oldI).forEach(prop => { const hasChanges = oldI[prop] instanceof Date ? - oldI[prop]?.getTime() != newI[prop]?.getTime() : - oldI[prop] != newI[prop]; + oldI[prop]?.getTime() != newI[prop]?.getTime() : + oldI[prop] != newI[prop]; if (!hasChanges) { delete oldI[prop]; @@ -537,13 +536,13 @@ exports.initialize = function initialize(dataSource, callback) { modelBuilder.defineValueType.bind(modelBuilder) : modelBuilder.constructor.registerType.bind(modelBuilder.constructor); - defineType(function Point() {}); + defineType(function Point() { }); dataSource.EnumFactory = EnumFactory; if (callback) { if (dataSource.settings.lazyConnect) { - process.nextTick(function() { + process.nextTick(function () { callback(); }); } else @@ -551,13 +550,13 @@ exports.initialize = function initialize(dataSource, callback) { } }; -MySQL.prototype.connect = function(callback) { +MySQL.prototype.connect = function (callback) { const self = this; const options = generateOptions(this.settings); if (this.client) { if (callback) { - process.nextTick(function() { + process.nextTick(function () { callback(null, self.client); }); } @@ -566,7 +565,7 @@ MySQL.prototype.connect = function(callback) { function connectionHandler(options, callback) { const client = mysql.createPool(options); - client.getConnection(function(err, connection) { + client.getConnection(function (err, connection) { const conn = connection; if (!err) { if (self.debug) @@ -645,3 +644,31 @@ function generateOptions(settings) { } return options; } + + +SQLConnector.prototype.all = function find(model, filter, options, cb) { + const self = this; + // Order by id if no order is specified + filter = filter || {}; + const stmt = this.buildSelect(model, filter, options); + this.execute(stmt.sql, stmt.params, options, function (err, data) { + if (err) { + return cb(err, []); + } + + try { + const objs = data.map(function (obj) { + return self.fromRow(model, obj); + }); + if (filter && filter.include) { + self.getModelDefinition(model).model.include( + objs, filter.include, options, cb, + ); + } else { + cb(null, objs); + } + } catch (error) { + cb(error, []) + } + }); +}; \ No newline at end of file