From c9e827b3e928b0e674b2455aea71d191864efb54 Mon Sep 17 00:00:00 2001 From: The Arcane Brony Date: Sun, 10 Oct 2021 17:55:48 +0200 Subject: [PATCH 1/4] Fix duplicate key --- api/assets/schemas.json | 2 +- api/src/routes/guilds/#guild_id/vanity-url.ts | 9 +++---- api/src/routes/invites/index.ts | 1 - bundle/scripts/build.js | 27 ++++++++++++++----- util/src/entities/Guild.ts | 8 ------ util/src/entities/Invite.ts | 3 +++ 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/api/assets/schemas.json b/api/assets/schemas.json index 4f1ab9a8..a12925e0 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -4744,7 +4744,7 @@ "type": "string" }, "permissions": { - "type": "bigint" + "type": "array" }, "color": { "type": "integer" diff --git a/api/src/routes/guilds/#guild_id/vanity-url.ts b/api/src/routes/guilds/#guild_id/vanity-url.ts index 7f2cea9e..061b317c 100644 --- a/api/src/routes/guilds/#guild_id/vanity-url.ts +++ b/api/src/routes/guilds/#guild_id/vanity-url.ts @@ -10,10 +10,10 @@ const InviteRegex = /\W/g; router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const { guild_id } = req.params; - const guild = await Guild.findOneOrFail({ where: { id: guild_id }, relations: ["vanity_url"] }); - if (!guild.vanity_url) return res.json({ code: null }); + const invite = await Invite.findOne({ where: {guild_id: guild_id, vanity_url: true} }); + if (!invite) return res.json({ code: null }); - return res.json({ code: guild.vanity_url_code, uses: guild.vanity_url.uses }); + return res.json({ code: invite.code, uses: invite.uses }); }); export interface VanityUrlSchema { @@ -33,12 +33,9 @@ router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" }) const invite = await Invite.findOne({ code }); if (invite) throw new HTTPError("Invite already exists"); - const guild = await Guild.findOneOrFail({ id: guild_id }); const { id } = await Channel.findOneOrFail({ guild_id, type: ChannelType.GUILD_TEXT }); Promise.all([ - Guild.update({ id: guild_id }, { vanity_url_code: code }), - Invite.delete({ code: guild.vanity_url_code }), new Invite({ code: code, uses: 0, diff --git a/api/src/routes/invites/index.ts b/api/src/routes/invites/index.ts index 0fcf7c86..185311bc 100644 --- a/api/src/routes/invites/index.ts +++ b/api/src/routes/invites/index.ts @@ -33,7 +33,6 @@ router.delete("/:code", route({}), async (req: Request, res: Response) => { await Promise.all([ Invite.delete({ code }), - Guild.update({ vanity_url_code: code }, { vanity_url_code: undefined }), emitEvent({ event: "INVITE_DELETE", guild_id: guild_id, diff --git a/bundle/scripts/build.js b/bundle/scripts/build.js index 69111c88..a9798eff 100644 --- a/bundle/scripts/build.js +++ b/bundle/scripts/build.js @@ -1,6 +1,22 @@ const { execSync } = require("child_process"); const path = require("path"); const fse = require("fs-extra"); +const { getSystemErrorMap } = require("util"); +const { argv } = require("process"); + +const dirs = ["api", "util", "cdn", "gateway", "bundle"]; + +const verbose = argv.includes("verbose") || argv.includes("v"); + +if(argv.includes("clean")){ + dirs.forEach(a=>{ + var d = "../"+a+"/dist"; + if(fse.existsSync(d)) { + fse.rmSync(d,{recursive: true}); + if(verbose) console.log(`Deleted ${d}!`); + } + }); +} fse.copySync(path.join(__dirname, "..", "..", "api", "assets"), path.join(__dirname, "..", "dist", "api", "assets")); fse.copySync( @@ -8,13 +24,12 @@ fse.copySync( path.join(__dirname, "..", "dist", "api", "client_test") ); fse.copySync(path.join(__dirname, "..", "..", "api", "locales"), path.join(__dirname, "..", "dist", "api", "locales")); -fse.copySync(path.join(__dirname, "..", "..", "api", "src"), path.join(__dirname, "..", "dist", "api", "src")); -fse.copySync(path.join(__dirname, "..", "..", "util", "src"), path.join(__dirname, "..", "dist", "util", "src")); -fse.copySync(path.join(__dirname, "..", "..", "cdn", "src"), path.join(__dirname, "..", "dist", "cdn", "src")); -fse.copySync(path.join(__dirname, "..", "..", "gateway", "src"), path.join(__dirname, "..", "dist", "gateway", "src")); -fse.copySync(path.join(__dirname, "..", "..", "bundle", "src"), path.join(__dirname, "..", "dist", "bundle", "src")); +dirs.forEach(a=>{ + fse.copySync("../"+a+"/src", "dist/"+a+"/src"); + if(verbose) console.log(`Copied ${"../"+a+"/dist"} -> ${"dist/"+a+"/src"}!`); +}); -console.log("Copying src files done"); +console.log("Copying src files done"); console.log("Compiling src files ..."); console.log( diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts index 35595191..157f0921 100644 --- a/util/src/entities/Guild.ts +++ b/util/src/entities/Guild.ts @@ -257,14 +257,6 @@ export class Guild extends BaseClass { @Column({ nullable: true }) unavailable?: boolean; - @Column({ nullable: true }) - @RelationId((guild: Guild) => guild.vanity_url) - vanity_url_code?: string; - - @JoinColumn({ name: "vanity_url_code" }) - @ManyToOne(() => Invite) - vanity_url?: Invite; - @Column({ nullable: true }) verification_level?: number; diff --git a/util/src/entities/Invite.ts b/util/src/entities/Invite.ts index 82556fab..d6b8f2f8 100644 --- a/util/src/entities/Invite.ts +++ b/util/src/entities/Invite.ts @@ -71,6 +71,9 @@ export class Invite extends BaseClass { @Column({ nullable: true }) target_user_type?: number; + @Column({ nullable: true}) + vanity_url?: boolean; + static async joinGuild(user_id: string, code: string) { const invite = await Invite.findOneOrFail({ code }); if (invite.uses++ >= invite.max_uses && invite.max_uses !== 0) await Invite.delete({ code }); From d38953439ccce8c7c1af87bdc038b45dc5ede4a3 Mon Sep 17 00:00:00 2001 From: The Arcane Brony Date: Sun, 10 Oct 2021 18:12:51 +0200 Subject: [PATCH 2/4] forgot to fix primary columns on invites --- util/src/entities/Invite.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/src/entities/Invite.ts b/util/src/entities/Invite.ts index d6b8f2f8..b3e00957 100644 --- a/util/src/entities/Invite.ts +++ b/util/src/entities/Invite.ts @@ -1,6 +1,6 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, RelationId, PrimaryColumn } from "typeorm"; import { Member } from "./Member"; -import { BaseClass, PrimaryIdColumn } from "./BaseClass"; +import { BaseClassWithoutId } from "./BaseClass"; import { Channel } from "./Channel"; import { Guild } from "./Guild"; import { User } from "./User"; @@ -8,8 +8,8 @@ import { User } from "./User"; export const PublicInviteRelation = ["inviter", "guild", "channel"]; @Entity("invites") -export class Invite extends BaseClass { - @PrimaryIdColumn() +export class Invite extends BaseClassWithoutId { + @PrimaryColumn() code: string; @Column() From 4b811d3b517801733d47553a5ba997a4d88ee369 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 10 Oct 2021 18:28:38 +0200 Subject: [PATCH 3/4] :bug: fix vanity url --- api/src/routes/guilds/#guild_id/vanity-url.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/api/src/routes/guilds/#guild_id/vanity-url.ts b/api/src/routes/guilds/#guild_id/vanity-url.ts index 061b317c..63173345 100644 --- a/api/src/routes/guilds/#guild_id/vanity-url.ts +++ b/api/src/routes/guilds/#guild_id/vanity-url.ts @@ -10,7 +10,7 @@ const InviteRegex = /\W/g; router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const { guild_id } = req.params; - const invite = await Invite.findOne({ where: {guild_id: guild_id, vanity_url: true} }); + const invite = await Invite.findOne({ where: { guild_id: guild_id, vanity_url: true } }); if (!invite) return res.json({ code: null }); return res.json({ code: invite.code, uses: invite.uses }); @@ -35,15 +35,7 @@ router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" }) const { id } = await Channel.findOneOrFail({ guild_id, type: ChannelType.GUILD_TEXT }); - Promise.all([ - new Invite({ - code: code, - uses: 0, - created_at: new Date(), - guild_id, - channel_id: id - }).save() - ]); + await Invite.update({ vanity_url: true, guild_id }, { code: code, channel_id: id }); return res.json({ code: code }); }); From 587e0a7120d18693a7f09e813c144a380c8d0a86 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 10 Oct 2021 18:28:50 +0200 Subject: [PATCH 4/4] added vanity db migration --- bundle/package.json | 2 +- .../migrations/1633881705509-VanityInvite.ts | 17 +++++++++++++++ util/src/migrations/migrate_db_engine.ts | 21 +++++++++---------- 3 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 util/src/migrations/1633881705509-VanityInvite.ts diff --git a/bundle/package.json b/bundle/package.json index eedbdd8c..404c6758 100644 --- a/bundle/package.json +++ b/bundle/package.json @@ -9,7 +9,7 @@ "start": "node scripts/build.js && node dist/bundle/src/start.js", "start:bundle": "node dist/bundle/src/start.js", "test": "echo \"Error: no test specified\" && exit 1", - "migrate": "node --require ts-node/register node_modules/typeorm/cli.js -f ../util/ormconfig.json migration:run" + "migrate": "cd ../util/ && npm i && node --require ts-node/register node_modules/typeorm/cli.js -f ../util/ormconfig.json migration:run" }, "repository": { "type": "git", diff --git a/util/src/migrations/1633881705509-VanityInvite.ts b/util/src/migrations/1633881705509-VanityInvite.ts new file mode 100644 index 00000000..af9b98ae --- /dev/null +++ b/util/src/migrations/1633881705509-VanityInvite.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class VanityInvite1633881705509 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + try { + await queryRunner.query(`ALTER TABLE "emojis" DROP COLUMN vanity_url_code`); + await queryRunner.query(`ALTER TABLE "emojis" DROP CONSTRAINT FK_c2c1809d79eb120ea0cb8d342ad`); + } catch (error) {} + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "emojis" ADD vanity_url_code varchar`); + await queryRunner.query( + `ALTER TABLE "emojis" ADD CONSTRAINT FK_c2c1809d79eb120ea0cb8d342ad FOREIGN KEY ("vanity_url_code") REFERENCES "invites"("code") ON DELETE NO ACTION ON UPDATE NO ACTION` + ); + } +} diff --git a/util/src/migrations/migrate_db_engine.ts b/util/src/migrations/migrate_db_engine.ts index 33024a8d..cd578fb2 100644 --- a/util/src/migrations/migrate_db_engine.ts +++ b/util/src/migrations/migrate_db_engine.ts @@ -1,6 +1,6 @@ import { config } from "dotenv"; config(); -import { BaseEntity, createConnection, EntityTarget } from "typeorm"; +import { createConnection, EntityTarget } from "typeorm"; import { initDatabase } from "../util/Database"; import "missing-native-js-functions"; import { @@ -15,7 +15,6 @@ import { Invite, Member, Message, - RateLimit, ReadState, Recipient, Relationship, @@ -30,9 +29,9 @@ import { } from ".."; async function main() { - if (!process.env.FROM) throw new Error("FROM database env connection string not set"); + if (!process.env.TO) throw new Error("TO database env connection string not set"); - // manually arrange them because of foreign key + // manually arrange them because of foreign keys const entities = [ User, Guild, @@ -57,12 +56,12 @@ async function main() { Attachment, ]; - const newDB = await initDatabase(); + const oldDB = await initDatabase(); // @ts-ignore - const oldDB = await createConnection({ - type: process.env.FROM.split(":")[0]?.replace("+srv", ""), - url: process.env.FROM, + const newDB = await createConnection({ + type: process.env.TO.split(":")[0]?.replace("+srv", ""), + url: process.env.TO, entities, name: "old", }); @@ -73,13 +72,12 @@ async function main() { const entity = e as EntityTarget; const entries = await oldDB.manager.find(entity); //@ts-ignore - console.log("migrated " + entries.length + " " + entity.name); + console.log("migrating " + entries.length + " " + entity.name + " ..."); for (const entry of entries) { console.log(i++); if (entry instanceof User) { - console.log("instance of User"); if (entry.bio == null) entry.bio = ""; if (entry.rights == null) entry.rights = "0"; if (entry.disabled == null) entry.disabled = false; @@ -115,8 +113,9 @@ async function main() { // await newDB.manager.update(entity, { id: entry.id }, entry); // } } + // @ts-ignore - console.log("migrated all " + entity.name); + console.log("migrating " + entries.length + " " + entity.name + " ..."); } } catch (error) { console.error((error as any).message);