Finally "fix" (hack) Prisma middleware bug

Middleware runs twice on question upsert?
This commit is contained in:
Isaac
2022-07-23 20:28:48 +01:00
parent e00ff4e831
commit 5f5ffca74c
9 changed files with 63 additions and 64 deletions

View File

@@ -17,33 +17,29 @@ const encryptedFields = [
// 'regex',
];
const encrypt = obj => {
const traverse = (obj, action) => {
for (const prop in obj) {
if (typeof obj[prop] === 'string' && obj[prop].length !== 0 && encryptedFields.includes(prop)) {
obj[prop] = cryptr.encrypt(obj[prop]);
if (encryptedFields.includes(prop) && typeof obj[prop] === 'string' && obj[prop].length !== 0) {
try {
// prevent double encryption bug (from nested writes - notably upserting questions in category update).
// not sure why it happens
if (action === 'ENCRYPT' && cryptr.decrypt(obj[prop])) continue; // don't encrypt if it already encrypted
else obj[prop] = cryptr[action.toLowerCase()](obj[prop]);
} catch {
// do nothing
}
} else if (typeof obj[prop] === 'object') {
obj[prop] = encrypt(obj[prop]);
}
}
return obj;
};
const decrypt = obj => {
for (const prop in obj) {
if (typeof obj[prop] === 'string' && obj[prop].length !== 0 && encryptedFields.includes(prop)) {
obj[prop] = cryptr.decrypt(obj[prop]);
} else if (typeof obj[prop] === 'object') {
obj[prop] = decrypt(obj[prop]);
obj[prop] = traverse(obj[prop], action);
}
}
return obj;
};
module.exports = async (params, next) => {
if (params.args.create) params.args.create = encrypt(params.args.create);
if (params.args.data) params.args.data = encrypt(params.args.data);
if (params.args.update) params.args.update = encrypt(params.args.update);
if (params.args.create) params.args.create = traverse(params.args.create, 'ENCRYPT');
if (params.args.data) params.args.data = traverse(params.args.data, 'ENCRYPT');
if (params.args.update) params.args.update = traverse(params.args.update, 'ENCRYPT');
let result = await next(params);
if (result) result = decrypt(result);
if (result) result = traverse(result, 'DECRYPT');
return result;
};

View File

@@ -0,0 +1,39 @@
const jsonFields = [
'pingRoles',
'requiredRoles',
'staffRoles',
'autoTag',
'blocklist',
'workingHours',
'options',
'pinnedMessages',
];
const traverse = (obj, action) => {
for (let prop in obj) {
if (prop === 'createMany') {
obj.create = obj[prop].data;
delete obj[prop];
prop = 'create';
traverse(obj[prop], action);
} else if (jsonFields.includes(prop) && obj[prop] !== null && obj[prop] !== undefined) {
if (action === 'SERIALISE' && typeof obj[prop] !== 'string') {
obj[prop] = JSON.stringify(obj[prop]);
} else if (action === 'PARSE' && typeof obj[prop] === 'string') {
obj[prop] = JSON.parse(obj[prop]);
}
} else if (typeof obj[prop] === 'object' && obj[prop] !== null && obj[prop] !== undefined) {
traverse(obj[prop], action);
}
}
return obj;
};
module.exports = async (params, next) => {
if (params.args.create) params.args.create = traverse(params.args.create, 'SERIALISE');
if (params.args.data) params.args.data = traverse(params.args.data, 'SERIALISE');
if (params.args.update) params.args.update = traverse(params.args.update, 'SERIALISE');
let result = await next(params);
if (result) result = traverse(result, 'PARSE');
return result;
};

View File

@@ -1,35 +0,0 @@
const jsonFields = [
'pingRoles',
'requiredRoles',
'staffRoles',
'autoTag',
'blocklist',
'workingHours',
'options',
'pinnedMessages',
];
const traverse = (obj, func) => {
for (const prop in obj) {
console.log(prop, typeof obj[prop], obj[prop]);
if (jsonFields.includes(prop) && obj[prop] !== null && obj[prop] !== undefined) {
obj[prop] = func(obj[prop]);
} else if (typeof obj[prop] === 'object') {
obj[prop] = traverse(obj[prop], func);
}
}
return obj;
};
module.exports = async (params, next) => {
if (process.env.DB_PROVIDER === 'sqlite') {
if (params.args.create) params.args.create = traverse(params.args.create, val => JSON.stringify(val));
if (params.args.data) params.args.data = traverse(params.args.data, val => JSON.stringify(val));
if (params.args.update) params.args.update = traverse(params.args.update, val => JSON.stringify(val));
let result = await next(params);
if (result) result = traverse(result, val => JSON.parse(val));
return result;
} else {
return await next(params);
}
};