2205 - Prevent relations to being logged in
gitea/salix/pipeline/head This commit has test failures
Details
gitea/salix/pipeline/head This commit has test failures
Details
This commit is contained in:
parent
731e411cf8
commit
d24f04912e
|
@ -0,0 +1 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('WorkerLog', '*', 'READ', 'ALLOW', 'ROLE', 'hr');
|
|
@ -2,6 +2,7 @@ const pick = require('object.pick');
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
|
// const relations = ctx.Model.relations;
|
||||||
Self.setup = function() {
|
Self.setup = function() {
|
||||||
Self.super_.setup.call(this);
|
Self.super_.setup.call(this);
|
||||||
};
|
};
|
||||||
|
@ -12,23 +13,33 @@ module.exports = function(Self) {
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx) {
|
Self.observe('before save', async function(ctx) {
|
||||||
let options = {};
|
const appModels = ctx.Model.app.models;
|
||||||
|
const options = {};
|
||||||
|
|
||||||
|
// Check for transactions
|
||||||
if (ctx.options && ctx.options.transaction)
|
if (ctx.options && ctx.options.transaction)
|
||||||
options.transaction = ctx.options.transaction;
|
options.transaction = ctx.options.transaction;
|
||||||
|
|
||||||
let oldInstance;
|
let oldInstance;
|
||||||
let oldInstanceFk;
|
|
||||||
let newInstance;
|
let newInstance;
|
||||||
|
|
||||||
if (ctx.data) {
|
if (ctx.data) {
|
||||||
oldInstanceFk = pick(ctx.currentInstance, Object.keys(ctx.data));
|
const changes = pick(ctx.currentInstance, Object.keys(ctx.data));
|
||||||
newInstance = await fkToValue(ctx.data, ctx);
|
newInstance = await fkToValue(ctx.data, ctx);
|
||||||
oldInstance = await fkToValue(oldInstanceFk, ctx);
|
oldInstance = await fkToValue(changes, ctx);
|
||||||
|
|
||||||
if (ctx.where && !ctx.currentInstance) {
|
if (ctx.where && !ctx.currentInstance) {
|
||||||
let fields = Object.keys(ctx.data);
|
const fields = Object.keys(ctx.data);
|
||||||
ctx.oldInstances = await ctx.Model.app.models[ctx.Model.definition.name].find({where: ctx.where, fields: fields}, options);
|
const modelName = modelDef.name;
|
||||||
|
|
||||||
|
ctx.oldInstances = await appModels[modelName].find({
|
||||||
|
where: ctx.where,
|
||||||
|
fields: fields
|
||||||
|
}, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get changes from created instance
|
||||||
if (ctx.isNewInstance)
|
if (ctx.isNewInstance)
|
||||||
newInstance = await fkToValue(ctx.instance.__data, ctx);
|
newInstance = await fkToValue(ctx.instance.__data, ctx);
|
||||||
|
|
||||||
|
@ -37,18 +48,24 @@ module.exports = function(Self) {
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.observe('before delete', async function(ctx) {
|
Self.observe('before delete', async function(ctx) {
|
||||||
|
const appModels = ctx.Model.app.models;
|
||||||
|
const definition = ctx.Model.definition;
|
||||||
|
const relations = ctx.Model.relations;
|
||||||
|
|
||||||
let options = {};
|
let options = {};
|
||||||
if (ctx.options && ctx.options.transaction)
|
if (ctx.options && ctx.options.transaction)
|
||||||
options.transaction = ctx.options.transaction;
|
options.transaction = ctx.options.transaction;
|
||||||
|
|
||||||
if (ctx.where) {
|
if (ctx.where) {
|
||||||
let affectedModel = ctx.Model.definition.name;
|
let affectedModel = definition.name;
|
||||||
let definition = ctx.Model.definition;
|
let deletedInstances = await appModels[affectedModel].find({
|
||||||
let deletedInstances = await ctx.Model.app.models[affectedModel].find({where: ctx.where}, options);
|
where: ctx.where
|
||||||
|
}, options);
|
||||||
|
|
||||||
let relation = definition.settings.log.relation;
|
let relation = definition.settings.log.relation;
|
||||||
|
|
||||||
if (relation) {
|
if (relation) {
|
||||||
let primaryKey = ctx.Model.relations[relation].keyFrom;
|
let primaryKey = relations[relation].keyFrom;
|
||||||
|
|
||||||
let arrangedDeletedInstances = [];
|
let arrangedDeletedInstances = [];
|
||||||
for (let i = 0; i < deletedInstances.length; i++) {
|
for (let i = 0; i < deletedInstances.length; i++) {
|
||||||
|
@ -69,6 +86,8 @@ module.exports = function(Self) {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function logDeletedInstances(ctx, loopBackContext) {
|
async function logDeletedInstances(ctx, loopBackContext) {
|
||||||
|
const appModels = ctx.Model.app.models;
|
||||||
|
const modelDef = ctx.Model.definition;
|
||||||
let options = {};
|
let options = {};
|
||||||
if (ctx.options && ctx.options.transaction)
|
if (ctx.options && ctx.options.transaction)
|
||||||
options.transaction = ctx.options.transaction;
|
options.transaction = ctx.options.transaction;
|
||||||
|
@ -78,14 +97,14 @@ module.exports = function(Self) {
|
||||||
if (loopBackContext)
|
if (loopBackContext)
|
||||||
userFk = loopBackContext.active.accessToken.userId;
|
userFk = loopBackContext.active.accessToken.userId;
|
||||||
|
|
||||||
let definition = ctx.Model.definition;
|
let definition = modelDef;
|
||||||
|
|
||||||
let changedModelValue = definition.settings.log.changedModelValue;
|
let changedModelValue = definition.settings.log.changedModelValue;
|
||||||
let logRecord = {
|
let logRecord = {
|
||||||
originFk: instance.originFk,
|
originFk: instance.originFk,
|
||||||
userFk: userFk,
|
userFk: userFk,
|
||||||
action: 'delete',
|
action: 'delete',
|
||||||
changedModel: ctx.Model.definition.name,
|
changedModel: modelDef.name,
|
||||||
changedModelId: instance.id,
|
changedModelId: instance.id,
|
||||||
changedModelValue: instance[changedModelValue],
|
changedModelValue: instance[changedModelValue],
|
||||||
oldInstance: instance,
|
oldInstance: instance,
|
||||||
|
@ -95,26 +114,44 @@ module.exports = function(Self) {
|
||||||
delete instance.originFk;
|
delete instance.originFk;
|
||||||
|
|
||||||
let logModel = definition.settings.log.model;
|
let logModel = definition.settings.log.model;
|
||||||
await ctx.Model.app.models[logModel].create(logRecord, options);
|
await appModels[logModel].create(logRecord, options);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get log values from a foreign key
|
||||||
async function fkToValue(instance, ctx) {
|
async function fkToValue(instance, ctx) {
|
||||||
|
const appModels = ctx.Model.app.models;
|
||||||
|
const relations = ctx.Model.relations;
|
||||||
let options = {};
|
let options = {};
|
||||||
|
|
||||||
|
// Check for transactions
|
||||||
if (ctx.options && ctx.options.transaction)
|
if (ctx.options && ctx.options.transaction)
|
||||||
options.transaction = ctx.options.transaction;
|
options.transaction = ctx.options.transaction;
|
||||||
|
|
||||||
let cleanInstance = JSON.parse(JSON.stringify(instance));
|
const instanceCopy = JSON.parse(JSON.stringify(instance));
|
||||||
let result = {};
|
const result = {};
|
||||||
for (let key in cleanInstance) {
|
for (const key in instanceCopy) {
|
||||||
let val = cleanInstance[key];
|
let value = instanceCopy[key];
|
||||||
if (val === undefined || val === null) continue;
|
|
||||||
for (let key1 in ctx.Model.relations) {
|
if (value instanceof Object)
|
||||||
let val1 = ctx.Model.relations[key1];
|
continue;
|
||||||
if (val1.keyFrom == key && key != 'id') {
|
|
||||||
let recordSet = await ctx.Model.app.models[val1.modelTo.modelName].findById(val, null, options);
|
if (value === undefined || value === null) continue;
|
||||||
|
|
||||||
|
for (let relationName in relations) {
|
||||||
|
const relation = relations[relationName];
|
||||||
|
if (relation.keyFrom == key && key != 'id') {
|
||||||
|
const model = relation.modelTo;
|
||||||
|
const modelName = relation.modelTo.modelName;
|
||||||
|
const properties = model && model.definition.properties;
|
||||||
|
const settings = model && model.definition.settings;
|
||||||
|
|
||||||
|
const recordSet = await appModels[modelName].findById(value, null, options);
|
||||||
|
|
||||||
|
const hasShowField = settings.log && settings.log.showField;
|
||||||
|
let showField = hasShowField && recordSet
|
||||||
|
&& recordSet[settings.log.showField];
|
||||||
|
|
||||||
let showField = val1.modelTo && val1.modelTo.definition.settings.log && val1.modelTo.definition.settings.log.showField && recordSet && recordSet[val1.modelTo.definition.settings.log.showField];
|
|
||||||
if (!showField) {
|
if (!showField) {
|
||||||
const showFieldNames = [
|
const showFieldNames = [
|
||||||
'name',
|
'name',
|
||||||
|
@ -122,7 +159,10 @@ module.exports = function(Self) {
|
||||||
'code'
|
'code'
|
||||||
];
|
];
|
||||||
for (field of showFieldNames) {
|
for (field of showFieldNames) {
|
||||||
if (val1.modelTo.definition.properties && val1.modelTo.definition.properties[field] && recordSet && recordSet[field]) {
|
const propField = properties && properties[field];
|
||||||
|
const recordField = recordSet && recordSet[field];
|
||||||
|
|
||||||
|
if (propField && recordField) {
|
||||||
showField = field;
|
showField = field;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -130,25 +170,29 @@ module.exports = function(Self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showField && recordSet && recordSet[showField]) {
|
if (showField && recordSet && recordSet[showField]) {
|
||||||
val = recordSet[showField];
|
value = recordSet[showField];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = recordSet && recordSet.id || val;
|
value = recordSet && recordSet.id || value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result[key] = val;
|
result[key] = value;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logInModel(ctx, loopBackContext) {
|
async function logInModel(ctx, loopBackContext) {
|
||||||
let options = {};
|
const appModels = ctx.Model.app.models;
|
||||||
|
const definition = ctx.Model.definition;
|
||||||
|
const defSettings = ctx.Model.definition.settings;
|
||||||
|
const relations = ctx.Model.relations;
|
||||||
|
|
||||||
|
const options = {};
|
||||||
if (ctx.options && ctx.options.transaction)
|
if (ctx.options && ctx.options.transaction)
|
||||||
options.transaction = ctx.options.transaction;
|
options.transaction = ctx.options.transaction;
|
||||||
|
|
||||||
let definition = ctx.Model.definition;
|
|
||||||
let primaryKey;
|
let primaryKey;
|
||||||
for (let property in definition.properties) {
|
for (let property in definition.properties) {
|
||||||
if (definition.properties[property].id) {
|
if (definition.properties[property].id) {
|
||||||
|
@ -163,11 +207,11 @@ module.exports = function(Self) {
|
||||||
// RELATIONS LOG
|
// RELATIONS LOG
|
||||||
let changedModelId;
|
let changedModelId;
|
||||||
|
|
||||||
if (ctx.instance && !definition.settings.log.relation) {
|
if (ctx.instance && !defSettings.log.relation) {
|
||||||
originId = ctx.instance.id;
|
originId = ctx.instance.id;
|
||||||
changedModelId = ctx.instance.id;
|
changedModelId = ctx.instance.id;
|
||||||
} else if (definition.settings.log.relation) {
|
} else if (defSettings.log.relation) {
|
||||||
primaryKey = ctx.Model.relations[definition.settings.log.relation].keyFrom;
|
primaryKey = relations[defSettings.log.relation].keyFrom;
|
||||||
|
|
||||||
if (ctx.where && ctx.where[primaryKey])
|
if (ctx.where && ctx.where[primaryKey])
|
||||||
originId = ctx.where[primaryKey];
|
originId = ctx.where[primaryKey];
|
||||||
|
@ -181,12 +225,16 @@ module.exports = function(Self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the changedModelValue to save and the instances changed in case its an updateAll
|
// Sets the changedModelValue to save and the instances changed in case its an updateAll
|
||||||
let showField = definition.settings.log.showField;
|
let showField = defSettings.log.showField;
|
||||||
let where;
|
let where;
|
||||||
if (showField && (!ctx.instance || !ctx.instance[showField]) && ctx.where) {
|
if (showField && (!ctx.instance || !ctx.instance[showField]) && ctx.where) {
|
||||||
changedModelId = [];
|
changedModelId = [];
|
||||||
where = [];
|
where = [];
|
||||||
let changedInstances = await ctx.Model.app.models[definition.name].find({where: ctx.where, fields: ['id', showField, primaryKey]}, options);
|
let changedInstances = await appModels[definition.name].find({
|
||||||
|
where: ctx.where,
|
||||||
|
fields: ['id', showField, primaryKey]
|
||||||
|
}, options);
|
||||||
|
|
||||||
changedInstances.forEach(element => {
|
changedInstances.forEach(element => {
|
||||||
where.push(element[showField]);
|
where.push(element[showField]);
|
||||||
changedModelId.push(element.id);
|
changedModelId.push(element.id);
|
||||||
|
@ -195,7 +243,6 @@ module.exports = function(Self) {
|
||||||
} else if (ctx.hookState.oldInstance)
|
} else if (ctx.hookState.oldInstance)
|
||||||
where = ctx.instance[showField];
|
where = ctx.instance[showField];
|
||||||
|
|
||||||
|
|
||||||
// Set oldInstance, newInstance, userFk and action
|
// Set oldInstance, newInstance, userFk and action
|
||||||
let oldInstance = {};
|
let oldInstance = {};
|
||||||
if (ctx.hookState.oldInstance)
|
if (ctx.hookState.oldInstance)
|
||||||
|
@ -211,14 +258,14 @@ module.exports = function(Self) {
|
||||||
|
|
||||||
let action = setActionType(ctx);
|
let action = setActionType(ctx);
|
||||||
|
|
||||||
removeUnloggableProperties(definition, oldInstance);
|
removeUnloggable(definition, oldInstance);
|
||||||
removeUnloggableProperties(definition, newInstance);
|
removeUnloggable(definition, newInstance);
|
||||||
|
|
||||||
let logRecord = {
|
let logRecord = {
|
||||||
originFk: originId,
|
originFk: originId,
|
||||||
userFk: userFk,
|
userFk: userFk,
|
||||||
action: action,
|
action: action,
|
||||||
changedModel: ctx.Model.definition.name,
|
changedModel: definition.name,
|
||||||
changedModelId: changedModelId, // Model property with an different data type will throw a NaN error
|
changedModelId: changedModelId, // Model property with an different data type will throw a NaN error
|
||||||
changedModelValue: where,
|
changedModelValue: where,
|
||||||
oldInstance: oldInstance,
|
oldInstance: oldInstance,
|
||||||
|
@ -226,9 +273,9 @@ module.exports = function(Self) {
|
||||||
};
|
};
|
||||||
|
|
||||||
let logsToSave = setLogsToSave(where, changedModelId, logRecord, ctx);
|
let logsToSave = setLogsToSave(where, changedModelId, logRecord, ctx);
|
||||||
let logModel = definition.settings.log.model;
|
let logModel = defSettings.log.model;
|
||||||
|
|
||||||
await ctx.Model.app.models[logModel].create(logsToSave, options);
|
await appModels[logModel].create(logsToSave, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -236,7 +283,7 @@ module.exports = function(Self) {
|
||||||
* @param {*} definition Model definition
|
* @param {*} definition Model definition
|
||||||
* @param {*} properties Modified object properties
|
* @param {*} properties Modified object properties
|
||||||
*/
|
*/
|
||||||
function removeUnloggableProperties(definition, properties) {
|
function removeUnloggable(definition, properties) {
|
||||||
const propList = Object.keys(properties);
|
const propList = Object.keys(properties);
|
||||||
const propDefs = new Map();
|
const propDefs = new Map();
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
Date: Fecha
|
||||||
Model: Modelo
|
Model: Modelo
|
||||||
Action: Acción
|
Action: Acción
|
||||||
Author: Autor
|
Author: Autor
|
||||||
|
|
|
@ -62,7 +62,8 @@
|
||||||
"url" : "/log",
|
"url" : "/log",
|
||||||
"state": "worker.card.workerLog",
|
"state": "worker.card.workerLog",
|
||||||
"component": "vn-worker-log",
|
"component": "vn-worker-log",
|
||||||
"description": "Log"
|
"description": "Log",
|
||||||
|
"acl": ["hr"]
|
||||||
}, {
|
}, {
|
||||||
"url": "/pbx",
|
"url": "/pbx",
|
||||||
"state": "worker.card.pbx",
|
"state": "worker.card.pbx",
|
||||||
|
|
Loading…
Reference in New Issue