mirror of
https://github.com/Hessenuk/DiscordTickets.git
synced 2024-12-23 00:03:09 +02:00
Finally "fix" (hack) Prisma middleware bug
Middleware runs twice on question upsert?
This commit is contained in:
parent
e00ff4e831
commit
5f5ffca74c
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,7 +6,7 @@ prisma/
|
|||||||
# files
|
# files
|
||||||
.env
|
.env
|
||||||
*.db
|
*.db
|
||||||
|
*.db-journal
|
||||||
*.log
|
*.log
|
||||||
*.lock
|
|
||||||
*-lock.*
|
*-lock.*
|
||||||
user/config.yml
|
user/config.yml
|
@ -194,7 +194,7 @@ model Ticket {
|
|||||||
closedAt DateTime?
|
closedAt DateTime?
|
||||||
closedBy User @relation(name: "TicketsClosedByUser", fields: [closedById], references: [id])
|
closedBy User @relation(name: "TicketsClosedByUser", fields: [closedById], references: [id])
|
||||||
closedById String @db.VarChar(19)
|
closedById String @db.VarChar(19)
|
||||||
closedReason String?
|
closedReason String? @db.Text
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
createdBy User @relation(name: "TicketsCreatedByUser", fields: [createdById], references: [id])
|
createdBy User @relation(name: "TicketsCreatedByUser", fields: [createdById], references: [id])
|
||||||
createdById String @db.VarChar(19)
|
createdById String @db.VarChar(19)
|
||||||
@ -216,7 +216,7 @@ model Ticket {
|
|||||||
referencesMessageId String @db.VarChar(19)
|
referencesMessageId String @db.VarChar(19)
|
||||||
referencesTicket Ticket? @relation(name: "TicketsReferencedByTicket", fields: [referencesTicketId], references: [id], onDelete: SetNull)
|
referencesTicket Ticket? @relation(name: "TicketsReferencedByTicket", fields: [referencesTicketId], references: [id], onDelete: SetNull)
|
||||||
referencesTicketId String? @db.VarChar(19)
|
referencesTicketId String? @db.VarChar(19)
|
||||||
topic String?
|
topic String? @db.Text
|
||||||
questionAnswers QuestionAnswer[]
|
questionAnswers QuestionAnswer[]
|
||||||
|
|
||||||
@@unique([guildId, number])
|
@@unique([guildId, number])
|
||||||
|
@ -194,7 +194,7 @@ model Ticket {
|
|||||||
closedAt DateTime?
|
closedAt DateTime?
|
||||||
closedBy User @relation(name: "TicketsClosedByUser", fields: [closedById], references: [id])
|
closedBy User @relation(name: "TicketsClosedByUser", fields: [closedById], references: [id])
|
||||||
closedById String @db.VarChar(19)
|
closedById String @db.VarChar(19)
|
||||||
closedReason String?
|
closedReason String? @db.Text
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
createdBy User @relation(name: "TicketsCreatedByUser", fields: [createdById], references: [id])
|
createdBy User @relation(name: "TicketsCreatedByUser", fields: [createdById], references: [id])
|
||||||
createdById String @db.VarChar(19)
|
createdById String @db.VarChar(19)
|
||||||
@ -216,7 +216,7 @@ model Ticket {
|
|||||||
referencesMessageId String @db.VarChar(19)
|
referencesMessageId String @db.VarChar(19)
|
||||||
referencesTicket Ticket? @relation(name: "TicketsReferencedByTicket", fields: [referencesTicketId], references: [id], onDelete: SetNull)
|
referencesTicket Ticket? @relation(name: "TicketsReferencedByTicket", fields: [referencesTicketId], references: [id], onDelete: SetNull)
|
||||||
referencesTicketId String? @db.VarChar(19)
|
referencesTicketId String? @db.VarChar(19)
|
||||||
topic String?
|
topic String? @db.Text
|
||||||
questionAnswers QuestionAnswer[]
|
questionAnswers QuestionAnswer[]
|
||||||
|
|
||||||
@@unique([guildId, number])
|
@@unique([guildId, number])
|
||||||
|
@ -4,7 +4,7 @@ generator client {
|
|||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "sqlite"
|
provider = "sqlite"
|
||||||
url = env("DB_CONNECTION_URL")
|
url = "file:../user/database.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
model ArchivedChannel {
|
model ArchivedChannel {
|
||||||
|
@ -7,7 +7,7 @@ const fs = require('fs');
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const YAML = require('yaml');
|
const YAML = require('yaml');
|
||||||
const encryptionMiddleware = require('./lib/middleware/prisma-encryption');
|
const encryptionMiddleware = require('./lib/middleware/prisma-encryption');
|
||||||
const typesMiddleware = require('./lib/middleware/prisma-types');
|
const sqliteMiddleware = require('./lib/middleware/prisma-sqlite');
|
||||||
|
|
||||||
module.exports = class Client extends FrameworkClient {
|
module.exports = class Client extends FrameworkClient {
|
||||||
constructor(config, log) {
|
constructor(config, log) {
|
||||||
@ -39,7 +39,7 @@ module.exports = class Client extends FrameworkClient {
|
|||||||
/** @type {PrismaClient} */
|
/** @type {PrismaClient} */
|
||||||
this.prisma = new PrismaClient();
|
this.prisma = new PrismaClient();
|
||||||
this.prisma.$use(encryptionMiddleware);
|
this.prisma.$use(encryptionMiddleware);
|
||||||
this.prisma.$use(typesMiddleware);
|
if (process.env.DB_PROVIDER === 'sqlite') this.prisma.$use(sqliteMiddleware);
|
||||||
this.keyv = new Keyv();
|
this.keyv = new Keyv();
|
||||||
return super.login(token);
|
return super.login(token);
|
||||||
}
|
}
|
||||||
|
@ -17,33 +17,29 @@ const encryptedFields = [
|
|||||||
// 'regex',
|
// 'regex',
|
||||||
];
|
];
|
||||||
|
|
||||||
const encrypt = obj => {
|
const traverse = (obj, action) => {
|
||||||
for (const prop in obj) {
|
for (const prop in obj) {
|
||||||
if (typeof obj[prop] === 'string' && obj[prop].length !== 0 && encryptedFields.includes(prop)) {
|
if (encryptedFields.includes(prop) && typeof obj[prop] === 'string' && obj[prop].length !== 0) {
|
||||||
obj[prop] = cryptr.encrypt(obj[prop]);
|
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') {
|
} else if (typeof obj[prop] === 'object') {
|
||||||
obj[prop] = encrypt(obj[prop]);
|
obj[prop] = traverse(obj[prop], action);
|
||||||
}
|
|
||||||
}
|
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = async (params, next) => {
|
module.exports = async (params, next) => {
|
||||||
if (params.args.create) params.args.create = encrypt(params.args.create);
|
if (params.args.create) params.args.create = traverse(params.args.create, 'ENCRYPT');
|
||||||
if (params.args.data) params.args.data = encrypt(params.args.data);
|
if (params.args.data) params.args.data = traverse(params.args.data, 'ENCRYPT');
|
||||||
if (params.args.update) params.args.update = encrypt(params.args.update);
|
if (params.args.update) params.args.update = traverse(params.args.update, 'ENCRYPT');
|
||||||
let result = await next(params);
|
let result = await next(params);
|
||||||
if (result) result = decrypt(result);
|
if (result) result = traverse(result, 'DECRYPT');
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
39
src/lib/middleware/prisma-sqlite.js
Normal file
39
src/lib/middleware/prisma-sqlite.js
Normal 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;
|
||||||
|
};
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
@ -78,8 +78,7 @@ module.exports.post = fastify => ({
|
|||||||
data: {
|
data: {
|
||||||
guild: { connect: { id: guild.id } },
|
guild: { connect: { id: guild.id } },
|
||||||
...data,
|
...data,
|
||||||
// questions: { createMany: { data: data.questions ?? [] } },
|
questions: { createMany: { data: data.questions ?? [] } },
|
||||||
questions: { create: { data: data.questions ?? [] } }, // sqlite doesn't support createMany?
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user