This commit is contained in:
parent
9f797edf00
commit
bebbe1c846
|
@ -6,11 +6,6 @@ module.exports = function(Self) {
|
||||||
Self.super_.setup.call(this);
|
Self.super_.setup.call(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
Self.observe('after save', async function(ctx) {
|
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
|
||||||
await logInModel(ctx, loopBackContext);
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx) {
|
Self.observe('before save', async function(ctx) {
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
const loopBackContext = LoopBackContext.getCurrentContext();
|
||||||
const models = ctx.Model.app.models;
|
const models = ctx.Model.app.models;
|
||||||
|
@ -21,10 +16,11 @@ module.exports = function(Self) {
|
||||||
if (!opts) opts = ctx.options = {};
|
if (!opts) opts = ctx.options = {};
|
||||||
|
|
||||||
// Check for transactions
|
// Check for transactions
|
||||||
let tx;
|
if (opts.txLevel)
|
||||||
if (!opts.transaction) {
|
opts.txLevel++;
|
||||||
opts.transaction = tx = await Model.beginTransaction({});
|
else if (!opts.transaction) {
|
||||||
opts.tx = true;
|
opts.txLevel = 1;
|
||||||
|
opts.transaction = await Model.beginTransaction({});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -59,11 +55,143 @@ module.exports = function(Self) {
|
||||||
ctx.hookState.oldInstance = oldInstance;
|
ctx.hookState.oldInstance = oldInstance;
|
||||||
ctx.hookState.newInstance = newInstance;
|
ctx.hookState.newInstance = newInstance;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (tx) await tx.rollback();
|
await txEnd(ctx, true);
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function txEnd(ctx, undoChanges) {
|
||||||
|
const opts = ctx.options || {};
|
||||||
|
if (opts.txLevel) {
|
||||||
|
opts.txLevel--;
|
||||||
|
if (opts.txLevel === 0) {
|
||||||
|
const tx = opts.transaction;
|
||||||
|
delete opts.txLevel;
|
||||||
|
delete opts.transaction;
|
||||||
|
|
||||||
|
if (undoChanges)
|
||||||
|
await tx.rollback();
|
||||||
|
else
|
||||||
|
await tx.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self.observe('after save', async function(ctx) {
|
||||||
|
const loopBackContext = LoopBackContext.getCurrentContext();
|
||||||
|
await logInModel(ctx, loopBackContext);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function logInModel(ctx, loopBackContext) {
|
||||||
|
const models = ctx.Model.app.models;
|
||||||
|
const definition = ctx.Model.definition;
|
||||||
|
const Model = models[definition.name];
|
||||||
|
const settings = ctx.Model.definition.settings;
|
||||||
|
const relations = ctx.Model.relations;
|
||||||
|
|
||||||
|
let opts = ctx.options;
|
||||||
|
if (!opts) opts = ctx.options = {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
let primaryKey;
|
||||||
|
for (let property in definition.properties) {
|
||||||
|
if (definition.properties[property].id) {
|
||||||
|
primaryKey = property;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!primaryKey) throw new Error('Primary key not found');
|
||||||
|
let originId;
|
||||||
|
|
||||||
|
// RELATIONS LOG
|
||||||
|
let changedModelId;
|
||||||
|
|
||||||
|
if (ctx.instance && !settings.log.relation) {
|
||||||
|
originId = ctx.instance.id;
|
||||||
|
changedModelId = ctx.instance.id;
|
||||||
|
} else if (settings.log.relation) {
|
||||||
|
primaryKey = relations[settings.log.relation].keyFrom;
|
||||||
|
|
||||||
|
if (ctx.where && ctx.where[primaryKey])
|
||||||
|
originId = ctx.where[primaryKey];
|
||||||
|
else if (ctx.instance) {
|
||||||
|
originId = ctx.instance[primaryKey];
|
||||||
|
changedModelId = ctx.instance.id;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
originId = ctx.currentInstance.id;
|
||||||
|
changedModelId = ctx.currentInstance.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the changedModelValue to save and the instances changed in case its an updateAll
|
||||||
|
let showField = settings.log.showField;
|
||||||
|
let where;
|
||||||
|
if (showField && (!ctx.instance || !ctx.instance[showField]) && ctx.where) {
|
||||||
|
changedModelId = [];
|
||||||
|
where = [];
|
||||||
|
let changedInstances = await models[definition.name].find({
|
||||||
|
where: ctx.where,
|
||||||
|
fields: ['id', showField, primaryKey]
|
||||||
|
}, opts);
|
||||||
|
|
||||||
|
changedInstances.forEach(element => {
|
||||||
|
where.push(element[showField]);
|
||||||
|
changedModelId.push(element.id);
|
||||||
|
originId = element[primaryKey];
|
||||||
|
});
|
||||||
|
} else if (ctx.hookState.oldInstance)
|
||||||
|
where = ctx.instance[showField];
|
||||||
|
|
||||||
|
// Set oldInstance, newInstance, userFk and action
|
||||||
|
let oldInstance = {};
|
||||||
|
if (ctx.hookState.oldInstance)
|
||||||
|
Object.assign(oldInstance, ctx.hookState.oldInstance);
|
||||||
|
|
||||||
|
let newInstance = {};
|
||||||
|
if (ctx.hookState.newInstance)
|
||||||
|
Object.assign(newInstance, ctx.hookState.newInstance);
|
||||||
|
|
||||||
|
let userFk;
|
||||||
|
if (loopBackContext)
|
||||||
|
userFk = loopBackContext.active.accessToken.userId;
|
||||||
|
|
||||||
|
const action = setActionType(ctx);
|
||||||
|
|
||||||
|
removeUnloggable(definition, oldInstance);
|
||||||
|
removeUnloggable(definition, newInstance);
|
||||||
|
|
||||||
|
oldInstance = await fkToValue(oldInstance, ctx);
|
||||||
|
newInstance = await fkToValue(newInstance, ctx);
|
||||||
|
|
||||||
|
// Prevent log with no new changes
|
||||||
|
const hasNewChanges = Object.keys(newInstance).length;
|
||||||
|
if (!hasNewChanges) return;
|
||||||
|
|
||||||
|
let logRecord = {
|
||||||
|
originFk: originId,
|
||||||
|
userFk: userFk,
|
||||||
|
action: action,
|
||||||
|
changedModel: definition.name,
|
||||||
|
changedModelId: changedModelId, // Model property with an different data type will throw a NaN error
|
||||||
|
changedModelValue: where,
|
||||||
|
oldInstance: oldInstance,
|
||||||
|
newInstance: newInstance
|
||||||
|
};
|
||||||
|
|
||||||
|
const logsToSave = setLogsToSave(where, changedModelId, logRecord, ctx);
|
||||||
|
const logModel = settings.log.model;
|
||||||
|
await models[logModel].create(logsToSave, opts);
|
||||||
|
|
||||||
|
// Check if grabUser is active
|
||||||
|
if (settings.log && settings.log.grabUser) await Model.rawSql(`CALL account.myUser_logout()`, null, opts);
|
||||||
|
} catch (e) {
|
||||||
|
await txEnd(ctx, true);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
await txEnd(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
Self.observe('before delete', async function(ctx) {
|
Self.observe('before delete', async function(ctx) {
|
||||||
const models = ctx.Model.app.models;
|
const models = ctx.Model.app.models;
|
||||||
const definition = ctx.Model.definition;
|
const definition = ctx.Model.definition;
|
||||||
|
@ -193,124 +321,6 @@ module.exports = function(Self) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logInModel(ctx, loopBackContext) {
|
|
||||||
const models = ctx.Model.app.models;
|
|
||||||
const definition = ctx.Model.definition;
|
|
||||||
const Model = models[definition.name];
|
|
||||||
const settings = ctx.Model.definition.settings;
|
|
||||||
const relations = ctx.Model.relations;
|
|
||||||
|
|
||||||
let opts = ctx.options;
|
|
||||||
if (!opts) opts = ctx.options = {};
|
|
||||||
|
|
||||||
// Check for transactions
|
|
||||||
let tx;
|
|
||||||
if (opts.tx === true) tx = opts.transaction;
|
|
||||||
|
|
||||||
try {
|
|
||||||
let primaryKey;
|
|
||||||
for (let property in definition.properties) {
|
|
||||||
if (definition.properties[property].id) {
|
|
||||||
primaryKey = property;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!primaryKey) throw new Error('Primary key not found');
|
|
||||||
let originId;
|
|
||||||
|
|
||||||
// RELATIONS LOG
|
|
||||||
let changedModelId;
|
|
||||||
|
|
||||||
if (ctx.instance && !settings.log.relation) {
|
|
||||||
originId = ctx.instance.id;
|
|
||||||
changedModelId = ctx.instance.id;
|
|
||||||
} else if (settings.log.relation) {
|
|
||||||
primaryKey = relations[settings.log.relation].keyFrom;
|
|
||||||
|
|
||||||
if (ctx.where && ctx.where[primaryKey])
|
|
||||||
originId = ctx.where[primaryKey];
|
|
||||||
else if (ctx.instance) {
|
|
||||||
originId = ctx.instance[primaryKey];
|
|
||||||
changedModelId = ctx.instance.id;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
originId = ctx.currentInstance.id;
|
|
||||||
changedModelId = ctx.currentInstance.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the changedModelValue to save and the instances changed in case its an updateAll
|
|
||||||
let showField = settings.log.showField;
|
|
||||||
let where;
|
|
||||||
if (showField && (!ctx.instance || !ctx.instance[showField]) && ctx.where) {
|
|
||||||
changedModelId = [];
|
|
||||||
where = [];
|
|
||||||
let changedInstances = await models[definition.name].find({
|
|
||||||
where: ctx.where,
|
|
||||||
fields: ['id', showField, primaryKey]
|
|
||||||
}, opts);
|
|
||||||
|
|
||||||
changedInstances.forEach(element => {
|
|
||||||
where.push(element[showField]);
|
|
||||||
changedModelId.push(element.id);
|
|
||||||
originId = element[primaryKey];
|
|
||||||
});
|
|
||||||
} else if (ctx.hookState.oldInstance)
|
|
||||||
where = ctx.instance[showField];
|
|
||||||
|
|
||||||
// Set oldInstance, newInstance, userFk and action
|
|
||||||
let oldInstance = {};
|
|
||||||
if (ctx.hookState.oldInstance)
|
|
||||||
Object.assign(oldInstance, ctx.hookState.oldInstance);
|
|
||||||
|
|
||||||
let newInstance = {};
|
|
||||||
if (ctx.hookState.newInstance)
|
|
||||||
Object.assign(newInstance, ctx.hookState.newInstance);
|
|
||||||
|
|
||||||
let userFk;
|
|
||||||
if (loopBackContext)
|
|
||||||
userFk = loopBackContext.active.accessToken.userId;
|
|
||||||
|
|
||||||
const action = setActionType(ctx);
|
|
||||||
|
|
||||||
removeUnloggable(definition, oldInstance);
|
|
||||||
removeUnloggable(definition, newInstance);
|
|
||||||
|
|
||||||
oldInstance = await fkToValue(oldInstance, ctx);
|
|
||||||
newInstance = await fkToValue(newInstance, ctx);
|
|
||||||
|
|
||||||
// Prevent log with no new changes
|
|
||||||
const hasNewChanges = Object.keys(newInstance).length;
|
|
||||||
if (!hasNewChanges) return;
|
|
||||||
|
|
||||||
let logRecord = {
|
|
||||||
originFk: originId,
|
|
||||||
userFk: userFk,
|
|
||||||
action: action,
|
|
||||||
changedModel: definition.name,
|
|
||||||
changedModelId: changedModelId, // Model property with an different data type will throw a NaN error
|
|
||||||
changedModelValue: where,
|
|
||||||
oldInstance: oldInstance,
|
|
||||||
newInstance: newInstance
|
|
||||||
};
|
|
||||||
|
|
||||||
const logsToSave = setLogsToSave(where, changedModelId, logRecord, ctx);
|
|
||||||
const logModel = settings.log.model;
|
|
||||||
await models[logModel].create(logsToSave, opts);
|
|
||||||
|
|
||||||
// Check if grabUser is active
|
|
||||||
if (settings.log && settings.log.grabUser) await Model.rawSql(`CALL account.myUser_logout()`, null, opts);
|
|
||||||
if (tx) {
|
|
||||||
await tx.commit();
|
|
||||||
delete opts.transaction;
|
|
||||||
delete opts.tx;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (tx) await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes unwanted properties
|
* Removes unwanted properties
|
||||||
* @param {*} definition Model definition
|
* @param {*} definition Model definition
|
||||||
|
|
Loading…
Reference in New Issue