diff --git a/api/src/routes/guilds/#guild_id/delete.ts b/api/src/routes/guilds/#guild_id/delete.ts
index 7c3c5530..bd158c56 100644
--- a/api/src/routes/guilds/#guild_id/delete.ts
+++ b/api/src/routes/guilds/#guild_id/delete.ts
@@ -13,15 +13,8 @@ router.post("/", route({}), async (req: Request, res: Response) => {
const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: ["owner_id"] });
if (guild.owner_id !== req.user_id) throw new HTTPError("You are not the owner of this guild", 401);
- // do not put everything into promise all, because of "QueryFailedError: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed"
-
- await Message.delete({ guild_id }); // messages must be deleted before channel
-
await Promise.all([
- Role.delete({ guild_id }),
- Channel.delete({ guild_id }),
- Emoji.delete({ guild_id }),
- Member.delete({ guild_id }),
+ Guild.delete({ id: guild_id }), // this will also delete all guild related data
emitEvent({
event: "GUILD_DELETE",
data: {
@@ -31,9 +24,6 @@ router.post("/", route({}), async (req: Request, res: Response) => {
} as GuildDeleteEvent)
]);
- await Invite.delete({ guild_id }); // invite must be deleted after channel
- await Guild.delete({ id: guild_id }); // guild must be deleted after everything else
-
return res.sendStatus(204);
});
diff --git a/util/src/entities/Application.ts b/util/src/entities/Application.ts
index 2092cd4e..fab3d93f 100644
--- a/util/src/entities/Application.ts
+++ b/util/src/entities/Application.ts
@@ -41,7 +41,9 @@ export class Application extends BaseClass {
verify_key: string;
@JoinColumn({ name: "team_id" })
- @ManyToOne(() => Team)
+ @ManyToOne(() => Team, {
+ onDelete: "CASCADE",
+ })
team?: Team;
@JoinColumn({ name: "guild_id" })
diff --git a/util/src/entities/Attachment.ts b/util/src/entities/Attachment.ts
index 82c5ecf5..7b4b17eb 100644
--- a/util/src/entities/Attachment.ts
+++ b/util/src/entities/Attachment.ts
@@ -31,7 +31,9 @@ export class Attachment extends BaseClass {
message_id: string;
@JoinColumn({ name: "message_id" })
- @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments)
+ @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments, {
+ onDelete: "CASCADE",
+ })
message: import("./Message").Message;
@BeforeRemove()
diff --git a/util/src/entities/Ban.ts b/util/src/entities/Ban.ts
index e8a6d648..9504bd8e 100644
--- a/util/src/entities/Ban.ts
+++ b/util/src/entities/Ban.ts
@@ -10,7 +10,9 @@ export class Ban extends BaseClass {
user_id: string;
@JoinColumn({ name: "user_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
user: User;
@Column({ nullable: true })
@@ -18,7 +20,9 @@ export class Ban extends BaseClass {
guild_id: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild: Guild;
@Column({ nullable: true })
diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts
index 8a0b7a26..d18757f2 100644
--- a/util/src/entities/BaseClass.ts
+++ b/util/src/entities/BaseClass.ts
@@ -6,6 +6,7 @@ import {
EntityMetadata,
FindConditions,
getConnection,
+ getManager,
PrimaryColumn,
RemoveOptions,
} from "typeorm";
@@ -79,44 +80,41 @@ export class BaseClassWithoutId extends BaseEntity {
return repository.decrement(conditions, propertyPath, value);
}
- static async delete<T>(criteria: FindConditions<T>, options?: RemoveOptions) {
- if (!criteria) throw new Error("You need to specify delete criteria");
-
- const repository = this.getRepository();
- const promises = repository.metadata.relations.map(async (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}`
- );
- }
- const id = (criteria as any)[foreignKey.referencedColumnNames[0]];
- if (!id) throw new Error("id missing in criteria options");
-
- if (x.relationType === "many-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" ||
- x.relationType === "one-to-many"
- ) {
- return getConnection()
- .getRepository(x.inverseEntityMetadata.target)
- .delete({ [foreignKey.columnNames[0]]: id });
- }
- });
- await Promise.all(promises);
- return super.delete(criteria, options);
- }
+ // static async delete<T>(criteria: FindConditions<T>, options?: RemoveOptions) {
+ // if (!criteria) throw new Error("You need to specify delete criteria");
+
+ // const repository = this.getRepository();
+ // const promises = repository.metadata.relations.map(async (x) => {
+ // if (x.orphanedRowAction !== "delete") 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}`
+ // );
+ // }
+ // const id = (criteria as any)[foreignKey.referencedColumnNames[0]];
+ // if (!id) throw new Error("id missing in criteria options " + foreignKey.referencedColumnNames);
+
+ // if (x.relationType === "many-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" ||
+ // x.relationType === "one-to-many"
+ // ) {
+ // return (x.inverseEntityMetadata.target as any).delete({ [foreignKey.columnNames[0]]: 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 74611eea..ece82bd0 100644
--- a/util/src/entities/Channel.ts
+++ b/util/src/entities/Channel.ts
@@ -45,7 +45,6 @@ export class Channel extends BaseClass {
@OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
recipients?: Recipient[];
@@ -57,7 +56,9 @@ export class Channel extends BaseClass {
guild_id?: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild: Guild;
@Column({ nullable: true })
@@ -110,35 +111,30 @@ export class Channel extends BaseClass {
@OneToMany(() => Invite, (invite: Invite) => invite.channel, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
invites?: Invite[];
@OneToMany(() => Message, (message: Message) => message.channel, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
messages?: Message[];
@OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
voice_states?: VoiceState[];
@OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
read_states?: ReadState[];
@OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
webhooks?: Webhook[];
diff --git a/util/src/entities/ConnectedAccount.ts b/util/src/entities/ConnectedAccount.ts
index 59a8f423..b8aa2889 100644
--- a/util/src/entities/ConnectedAccount.ts
+++ b/util/src/entities/ConnectedAccount.ts
@@ -11,7 +11,9 @@ export class ConnectedAccount extends BaseClass {
user_id: string;
@JoinColumn({ name: "user_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
user: User;
@Column({ select: false })
diff --git a/util/src/entities/Emoji.ts b/util/src/entities/Emoji.ts
index 181aff2c..a252d9f4 100644
--- a/util/src/entities/Emoji.ts
+++ b/util/src/entities/Emoji.ts
@@ -15,7 +15,9 @@ export class Emoji extends BaseClass {
guild_id: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild: Guild;
@Column()
diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts
index d46d2161..e107937d 100644
--- a/util/src/entities/Guild.ts
+++ b/util/src/entities/Guild.ts
@@ -84,7 +84,6 @@ export class Guild extends BaseClass {
@OneToMany(() => Ban, (ban: Ban) => ban.guild, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
bans: Ban[];
@@ -147,7 +146,6 @@ export class Guild extends BaseClass {
@OneToMany(() => Channel, (channel: Channel) => channel.guild, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
channels: Channel[];
diff --git a/util/src/entities/Invite.ts b/util/src/entities/Invite.ts
index afad9c02..cb308823 100644
--- a/util/src/entities/Invite.ts
+++ b/util/src/entities/Invite.ts
@@ -34,7 +34,9 @@ export class Invite extends BaseClass {
guild_id: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild: Guild;
@Column({ nullable: true })
@@ -42,7 +44,9 @@ export class Invite extends BaseClass {
channel_id: string;
@JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel)
+ @ManyToOne(() => Channel, {
+ onDelete: "CASCADE",
+ })
channel: Channel;
@Column({ nullable: true })
@@ -58,7 +62,9 @@ export class Invite extends BaseClass {
target_user_id: string;
@JoinColumn({ name: "target_user_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
target_user?: string; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62
@Column({ nullable: true })
diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts
index 66f5d9a1..feb9c069 100644
--- a/util/src/entities/Member.ts
+++ b/util/src/entities/Member.ts
@@ -39,7 +39,9 @@ export class Member extends BaseClassWithoutId {
id: string;
@JoinColumn({ name: "id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
user: User;
@Column()
@@ -47,7 +49,9 @@ export class Member extends BaseClassWithoutId {
guild_id: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild: Guild;
@Column({ nullable: true })
@@ -55,7 +59,6 @@ export class Member extends BaseClassWithoutId {
@JoinTable({
name: "member_roles",
-
joinColumn: { name: "index", referencedColumnName: "index" },
inverseJoinColumn: {
name: "role_id",
diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts
index 0712f545..c4901693 100644
--- a/util/src/entities/Message.ts
+++ b/util/src/entities/Message.ts
@@ -54,7 +54,9 @@ export class Message extends BaseClass {
channel_id: string;
@JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel)
+ @ManyToOne(() => Channel, {
+ onDelete: "CASCADE",
+ })
channel: Channel;
@Column({ nullable: true })
@@ -62,7 +64,9 @@ export class Message extends BaseClass {
guild_id?: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild?: Guild;
@Column({ nullable: true })
@@ -70,7 +74,9 @@ export class Message extends BaseClass {
author_id: string;
@JoinColumn({ name: "author_id", referencedColumnName: "id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
author?: User;
@Column({ nullable: true })
@@ -132,7 +138,6 @@ export class Message extends BaseClass {
@OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, {
cascade: true,
orphanedRowAction: "delete",
- onDelete: "CASCADE",
})
attachments?: Attachment[];
diff --git a/util/src/entities/ReadState.ts b/util/src/entities/ReadState.ts
index 8dd05b21..68e867a0 100644
--- a/util/src/entities/ReadState.ts
+++ b/util/src/entities/ReadState.ts
@@ -15,7 +15,9 @@ export class ReadState extends BaseClass {
channel_id: string;
@JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel)
+ @ManyToOne(() => Channel, {
+ onDelete: "CASCADE",
+ })
channel: Channel;
@Column({ nullable: true })
@@ -23,7 +25,9 @@ export class ReadState extends BaseClass {
user_id: string;
@JoinColumn({ name: "user_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
user: User;
@Column({ nullable: true })
diff --git a/util/src/entities/Recipient.ts b/util/src/entities/Recipient.ts
index bb280588..a945f938 100644
--- a/util/src/entities/Recipient.ts
+++ b/util/src/entities/Recipient.ts
@@ -8,7 +8,9 @@ export class Recipient extends BaseClass {
channel_id: string;
@JoinColumn({ name: "channel_id" })
- @ManyToOne(() => require("./Channel").Channel)
+ @ManyToOne(() => require("./Channel").Channel, {
+ onDelete: "CASCADE",
+ })
channel: import("./Channel").Channel;
@Column()
@@ -16,7 +18,9 @@ export class Recipient extends BaseClass {
user_id: string;
@JoinColumn({ name: "user_id" })
- @ManyToOne(() => require("./User").User)
+ @ManyToOne(() => require("./User").User, {
+ onDelete: "CASCADE",
+ })
user: import("./User").User;
@Column({ default: false })
diff --git a/util/src/entities/Relationship.ts b/util/src/entities/Relationship.ts
index 61b3ac82..e016b36b 100644
--- a/util/src/entities/Relationship.ts
+++ b/util/src/entities/Relationship.ts
@@ -17,7 +17,9 @@ export class Relationship extends BaseClass {
from_id: string;
@JoinColumn({ name: "from_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
from: User;
@Column({})
@@ -25,7 +27,9 @@ export class Relationship extends BaseClass {
to_id: string;
@JoinColumn({ name: "to_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
to: User;
@Column({ nullable: true })
diff --git a/util/src/entities/Role.ts b/util/src/entities/Role.ts
index 33c8d272..9fca99a5 100644
--- a/util/src/entities/Role.ts
+++ b/util/src/entities/Role.ts
@@ -10,7 +10,9 @@ export class Role extends BaseClass {
guild_id: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild: Guild;
@Column()
diff --git a/util/src/entities/Session.ts b/util/src/entities/Session.ts
index d42a8f98..7cc325f5 100644
--- a/util/src/entities/Session.ts
+++ b/util/src/entities/Session.ts
@@ -11,7 +11,9 @@ export class Session extends BaseClass {
user_id: string;
@JoinColumn({ name: "user_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
user: User;
//TODO check, should be 32 char long hex string
diff --git a/util/src/entities/Sticker.ts b/util/src/entities/Sticker.ts
index 7730a86a..ab224d1d 100644
--- a/util/src/entities/Sticker.ts
+++ b/util/src/entities/Sticker.ts
@@ -31,7 +31,9 @@ export class Sticker extends BaseClass {
guild_id?: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild?: Guild;
@Column({ type: "simple-enum", enum: StickerType })
diff --git a/util/src/entities/Team.ts b/util/src/entities/Team.ts
index beb8bf68..22140b7f 100644
--- a/util/src/entities/Team.ts
+++ b/util/src/entities/Team.ts
@@ -9,7 +9,9 @@ export class Team extends BaseClass {
icon?: string;
@JoinColumn({ name: "member_ids" })
- @OneToMany(() => TeamMember, (member: TeamMember) => member.team)
+ @OneToMany(() => TeamMember, (member: TeamMember) => member.team, {
+ orphanedRowAction: "delete",
+ })
members: TeamMember[];
@Column()
diff --git a/util/src/entities/TeamMember.ts b/util/src/entities/TeamMember.ts
index 6b184d08..bdfdccf0 100644
--- a/util/src/entities/TeamMember.ts
+++ b/util/src/entities/TeamMember.ts
@@ -20,7 +20,9 @@ export class TeamMember extends BaseClass {
team_id: string;
@JoinColumn({ name: "team_id" })
- @ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members)
+ @ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members, {
+ onDelete: "CASCADE",
+ })
team: import("./Team").Team;
@Column({ nullable: true })
@@ -28,6 +30,8 @@ export class TeamMember extends BaseClass {
user_id: string;
@JoinColumn({ name: "user_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
user: User;
}
diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts
index cef88777..4c86b2d8 100644
--- a/util/src/entities/User.ts
+++ b/util/src/entities/User.ts
@@ -127,11 +127,17 @@ export class User extends BaseClass {
public_flags: number;
@JoinColumn({ name: "relationship_ids" })
- @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from)
+ @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ })
relationships: Relationship[];
@JoinColumn({ name: "connected_account_ids" })
- @OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user)
+ @OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ })
connected_accounts: ConnectedAccount[];
@Column({ type: "simple-json", select: false })
diff --git a/util/src/entities/VoiceState.ts b/util/src/entities/VoiceState.ts
index 56eb244e..75748a01 100644
--- a/util/src/entities/VoiceState.ts
+++ b/util/src/entities/VoiceState.ts
@@ -13,7 +13,9 @@ export class VoiceState extends BaseClass {
guild_id: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild?: Guild;
@Column({ nullable: true })
@@ -21,7 +23,9 @@ export class VoiceState extends BaseClass {
channel_id: string;
@JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel)
+ @ManyToOne(() => Channel, {
+ onDelete: "CASCADE",
+ })
channel: Channel;
@Column({ nullable: true })
@@ -29,11 +33,15 @@ export class VoiceState extends BaseClass {
user_id: string;
@JoinColumn({ name: "user_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
user: User;
// @JoinColumn([{ name: "user_id", referencedColumnName: "id" },{ name: "guild_id", referencedColumnName: "guild_id" }])
- // @ManyToOne(() => Member)
+ // @ManyToOne(() => Member, {
+ // onDelete: "CASCADE",
+ // })
//TODO find a way to make it work without breaking Guild.voice_states
member: Member;
diff --git a/util/src/entities/Webhook.ts b/util/src/entities/Webhook.ts
index 12ba0d08..8382435f 100644
--- a/util/src/entities/Webhook.ts
+++ b/util/src/entities/Webhook.ts
@@ -32,7 +32,9 @@ export class Webhook extends BaseClass {
guild_id: string;
@JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
guild: Guild;
@Column({ nullable: true })
@@ -40,7 +42,9 @@ export class Webhook extends BaseClass {
channel_id: string;
@JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel)
+ @ManyToOne(() => Channel, {
+ onDelete: "CASCADE",
+ })
channel: Channel;
@Column({ nullable: true })
@@ -48,7 +52,9 @@ export class Webhook extends BaseClass {
application_id: string;
@JoinColumn({ name: "application_id" })
- @ManyToOne(() => Application)
+ @ManyToOne(() => Application, {
+ onDelete: "CASCADE",
+ })
application: Application;
@Column({ nullable: true })
@@ -56,7 +62,9 @@ export class Webhook extends BaseClass {
user_id: string;
@JoinColumn({ name: "user_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE",
+ })
user: User;
@Column({ nullable: true })
@@ -64,6 +72,8 @@ export class Webhook extends BaseClass {
source_guild_id: string;
@JoinColumn({ name: "source_guild_id" })
- @ManyToOne(() => Guild)
+ @ManyToOne(() => Guild, {
+ onDelete: "CASCADE",
+ })
source_guild: Guild;
}
|