From ce09e01c2154072dfb52fceaca33a6106d2e1220 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 20 Sep 2021 17:11:22 +0200 Subject: [PATCH] :construction: auto delete relations --- api/src/routes/channels/#channel_id/index.ts | 20 +++++--- util/package-lock.json | Bin 459190 -> 459116 bytes util/src/entities/BaseClass.ts | 49 ++++++++++++++++++- util/src/entities/Channel.ts | 12 +---- util/src/util/Database.ts | 2 +- 5 files changed, 64 insertions(+), 19 deletions(-) diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts index 3f434f5e..1063b151 100644 --- a/api/src/routes/channels/#channel_id/index.ts +++ b/api/src/routes/channels/#channel_id/index.ts @@ -1,6 +1,15 @@ -import { Channel, ChannelDeleteEvent, ChannelPermissionOverwriteType, ChannelType, ChannelUpdateEvent, emitEvent, Recipient } from "@fosscord/util"; +import { + Channel, + ChannelDeleteEvent, + ChannelPermissionOverwriteType, + ChannelType, + ChannelUpdateEvent, + emitEvent, + Recipient, + handleFile +} from "@fosscord/util"; import { Request, Response, Router } from "express"; -import { handleFile, route } from "@fosscord/api"; +import { route } from "@fosscord/api"; const router: Router = Router(); // TODO: delete channel @@ -20,15 +29,14 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] }); if (channel.type === ChannelType.DM) { - const recipient = await Recipient.findOneOrFail({ where: { channel_id: channel_id, user_id: req.user_id } }) - recipient.closed = true + const recipient = await Recipient.findOneOrFail({ where: { channel_id: channel_id, user_id: req.user_id } }); + recipient.closed = true; await Promise.all([ recipient.save(), emitEvent({ event: "CHANNEL_DELETE", data: channel, user_id: req.user_id } as ChannelDeleteEvent) ]); - } else if (channel.type === ChannelType.GROUP_DM) { - await Channel.removeRecipientFromChannel(channel, req.user_id) + await Channel.removeRecipientFromChannel(channel, req.user_id); } else { //TODO messages in this channel should be deleted before deleting the channel await Promise.all([ diff --git a/util/package-lock.json b/util/package-lock.json index e5a62d0f36a1fa06c3e0b137b0fd5e4f3349a0d8..f412961430c0fff63d0f6f363743b7c9e0762666 100644 GIT binary patch delta 1821 zcmciBOKjV890zbYb{oiO8Csb}N!o^qmCY1C@^Zv8Pq(oXI}fL^>BVv4yp!hbRGQRw znu>%(5tjH%2*#ud&SjCXgpi7aI3OX!P<_ibh{^%HE-f3e!Z_GQz8AjO*Ha-7C|-LRUkgi|8wsf*4; z!Jn*D3#qQxgDajy*-^tHTydrAVtBvMP5Hb&(Y+xviqNY#3+_-hn92F;#gfAn_O;u& zv9W50ps5W%v+6#?p!5 z`{(=956aRvS+gFcW{xXr4HPNUi=$f78y~DF5$|#)A6!+5uGXw((_x>`#1lstOS0GG3`KDRd zJ~##B>!X|0OTMy_?-xR1FUbd_nuC+0-ho?;w^%Y6;+MVrpw)Jmb7aq#}0%HtFpbF#hbAMO?)3J{AB2KJ|*b3ncZEhH0u|A3?2 z+G<8v#{&rxTNOyTmf3K$J7s1)S#?DSO>la{M4jZcAcl4Q66fp(7@FWYtnHy z>U1WhUa5xDnXW%kV!-b&K^J!R*C1nm&Gf|&;LCSL+rIwB@9H)T>Tz4gNr}HX8q=pWhCrzNWZ%K@PpVO|9}@xj0@cT*RUOrvu{GC z!QP+n$>EOI4uPW?)t#=Hye2biJUi>~fodr)%`1kdLBy?puc{e6CW z!+Gyb=bf8Qu&@#xEGf+y1;SjdYB$2f;cXAQc}iX{SmR)wRFn6 z(Z^$wR*NUHy+*fZ36vj?M@vJ`hQ7K%NZsc!9V&o3gV z?-d&SemW2B$LJKWFAHGjWykL3;^Aq;2b+&j0@%wl;PKi;ICqS`FwXWKq05>bPxs|C zp~)oA@v2hZikVcdU9NCu-cQe_X<6ZLjQE?ZketJF32xE%L9y^G3Og3DNg}hYQh*2?;YUYS+Xx-c3Rk!SqmY9^ks^wcg zl5Q%4W;^YQR1i>8o&cQt1wbV#sPK=D^e|(TE^EDxvrjJ;JH)C%IIhY`BH*zWQu@)TtnPo@8czHpft2vLJA4>Dlhas-oBI$tmo8j zy%q{KaXhAW`dlbZRLX;pK&LaTwk{a0ywD3z#H<8i9%~PNK2yuPN1q*LG7GVAebAsbnF)geVan9wkR5fj7N-VE+@Sad_7QF@g{OBya^0{Lc@qj(oOHfWB3!`rt^v(wpbO%oo*xI}M*m-#2Yjhgk{ssN+-wK^$ zeXk)<{tJB$?*D+Uy~92|x_OAMIwlSho?JoZNBhU<^>hC}H@N)`G7raP)9{N6*vx40 zPc(UbGW15iP3)`mB=Etz_pyc1$vy0doshTr8wXFY(ZQ3c0+^ULc=sZ9`9I)B?2co# F^*4PsW#|9^ diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts index 9b2ce058..2a621f40 100644 --- a/util/src/entities/BaseClass.ts +++ b/util/src/entities/BaseClass.ts @@ -1,5 +1,14 @@ import "reflect-metadata"; -import { BaseEntity, BeforeInsert, BeforeUpdate, EntityMetadata, FindConditions, PrimaryColumn } from "typeorm"; +import { + BaseEntity, + BeforeInsert, + BeforeUpdate, + EntityMetadata, + FindConditions, + getConnection, + PrimaryColumn, + RemoveOptions, +} from "typeorm"; import { Snowflake } from "../util/Snowflake"; import "missing-native-js-functions"; @@ -69,6 +78,44 @@ export class BaseClassWithoutId extends BaseEntity { const repository = this.getRepository(); return repository.decrement(conditions, propertyPath, value); } + + static async delete(criteria: FindConditions, options?: RemoveOptions) { + if (!criteria) throw new Error("You need to specify delete criteria"); + + const repository = this.getRepository(); + const promises = repository.metadata.relations.map((x) => { + if (x.orphanedRowAction !== "delete") return; + if (typeof x.type === "string") return; + + const foreignKey = + x.foreignKeys.find((key) => key.entityMetadata === repository.metadata) || + x.inverseRelation?.foreignKeys[0]; // find foreign key for this entity + if (!foreignKey) { + throw new Error( + `Foreign key not found for entity ${repository.metadata.name} in relation ${x.propertyName}` + ); + } + console.log(foreignKey); + const id = (criteria as any)[foreignKey.referencedColumnNames[0]]; + if (!id) throw new Error("id missing in criteria options"); + + if (x.relationType === "many-to-many" || x.relationType === "one-to-many") { + return getConnection() + .createQueryBuilder() + .relation(this, x.propertyName) + .of(id) + .remove({ [foreignKey.columnNames[0]]: id }); + } else if (x.relationType === "one-to-one" || x.relationType === "many-to-one") { + return getConnection() + .createQueryBuilder() + .from(x.inverseEntityMetadata, "user") + .of(id) + .remove({ [foreignKey.name]: id }); + } + }); + await Promise.all(promises); + return super.delete(criteria, options); + } } export class BaseClass extends BaseClassWithoutId { diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index b1f75f33..74611eea 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -1,14 +1,4 @@ -import { - Column, - Entity, - FindConditions, - JoinColumn, - ManyToOne, - ObjectID, - OneToMany, - RelationId, - RemoveOptions, -} from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { PublicUserProjection, User } from "./User"; diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts index d3844cd9..c22d8abd 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts @@ -21,7 +21,7 @@ export function initDatabase() { // entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"), synchronize: true, - logging: false, + logging: true, cache: { duration: 1000 * 3, // cache all find queries for 3 seconds },