From b8849adbdd8a06b11e92736c905a821d7c687217 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Mar 2022 13:14:49 +0000 Subject: [PATCH 01/53] Bump minimist from 1.2.5 to 1.2.6 in /api Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] --- api/package-lock.json | Bin 551645 -> 552367 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/api/package-lock.json b/api/package-lock.json index 1aa41056974f6ce6cf07fe6a8dd6a72da9ef1338..de8891880a292180749519b284ec5bc0e9de96cb 100644 GIT binary patch delta 597 zcmcb6RdM}o#fB}6MSYBB(cg12hI&SNX44OrvPj368XD<( z6=&sTn Date: Wed, 30 Mar 2022 13:21:03 +0000 Subject: [PATCH 02/53] Bump minimist from 1.2.5 to 1.2.6 in /gateway Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] --- gateway/package-lock.json | Bin 539847 -> 540149 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/gateway/package-lock.json b/gateway/package-lock.json index 9b3841af559bbe02f48e551e1414a5cd87c216e2..38bdab908fc6a1aeff1cbaafc27c1fbfeea0e905 100644 GIT binary patch delta 575 zcmX^9Q{n4xg@zW!Elhk|jAqjvBbfEXb2IZYb2E!e^mX-NOkG1gqv;b`*kz|LILpi$ zQk<2SZIV=O9O+dUS(TJh>6GbL91!jikmj$g9qR6GZerRf6Xk#3S#l$w`l z<{wt!A6Zcp7*beXZs3($UZNe8nr2ayo?e=p9pY1EIoV;|z8~3G88{XEr^bgic13YL;YRC3fzl}O#L$=GBP64&C;|BOS~*fGo!QvLMyUe!jscI zBYdVS{AW~df6K+R{Vf-B@>AMbG`TTYq+Q`7GZ3?ESNO>Kz;F7+0yeoYn)s@`{h$Ne Y_Ja=W*6p Date: Wed, 30 Mar 2022 14:18:45 +0000 Subject: [PATCH 03/53] Bump minimist from 1.2.5 to 1.2.6 in /cdn Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] --- cdn/package-lock.json | Bin 500169 -> 500169 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/cdn/package-lock.json b/cdn/package-lock.json index b48833b076dd387b74c2850d5c54837b8e4b1612..e6e9bb1abccc840399e90968c048b60985fb5720 100644 GIT binary patch delta 267 zcmX?kSnlLuxrP?T7N#xCG7{5&FtX`SS2)BbG2NMoO(E2)I4dvPB&pmu(yK7CDk-JX zDbuewAlxG$&0kwP)ZN|O#L~H<*sLJcxzscw-6XFlH80W3Kdiz(vZ5$3q_Di)z$>@B zL^~)o&7vqhy)-vF#HY$~`o>absp;H%7-gn^Sj@;W{njD2>(dL?Gm5qUmt+QF79eKb Y{$G;q({eQTgwe!3f!o&|Vw1iP06Ax2H~;_u delta 267 zcmX?kSnlLuxrP?T7N#xCG7{4#6*1~hS2)BbF}>(BvqG4guVtQJXk<~4lcTFoRA7j4 zMQT)_d0MWozf-zdUbtVbmv=~Vda+k(qEB&2fPSdIOIU$>agnKiMnpzNM7mj;c43K^ zMQLV~c0g!Fwo7<&x@Uw>`Q(pWlGC~OFv?8-u$Yl$`mIB3*QXb(XB2DyFUbtVEI`b< U{l6sJr{(l<&-QhP*re|R0M0pKtpET3 From 0a4c7b168c6cc025c47617592e1907246ee7c2a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Mar 2022 14:18:18 +0000 Subject: [PATCH 04/53] Bump minimist from 1.2.5 to 1.2.6 in /util Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] --- util/package-lock.json | Bin 498021 -> 498021 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/util/package-lock.json b/util/package-lock.json index 82e90b36f9bc99bad6791cc4f7da121e8bc7fa07..b2fa8bbf7bc938c62960c99604ad83a0c443f9d9 100644 GIT binary patch delta 258 zcmaF5N$%+;xrP?TEli!$raK*G)t^4$8w<D*PiWiULCl%gYVC za?4A!gHqEhiqg|dbF)Kysw@Mi2X-(?wI@tx0%B$$X4#%Foi%1R{T$F<8O*l5GMN31 FD*%8qUZ4N~ delta 266 zcmaF5N$%+;xrP?TEli!$rZ=TA>QA5WjfG|U`ye)v>4(!8Wu_~9W@HWVwaoJijVuas za&+~H3Jfu>NR0|KPs{c7cS<+Q3-`wuJ$^b95HkZY%l7!`tg*Xsx*?PnZYXcB N3})M28O;916#&EgU*`Y- From 296949786d5441194ad4fdae6a1c752b7ae31093 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Mar 2022 14:20:32 +0000 Subject: [PATCH 05/53] Bump minimist from 1.2.5 to 1.2.6 in /bundle Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] --- bundle/package-lock.json | Bin 595620 -> 595770 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bundle/package-lock.json b/bundle/package-lock.json index f6e46bc1e4402e8b5b975e136af210af758e5cac..4742b4a41a576991b6f81df3d4c826cc158d4745 100644 GIT binary patch delta 313 zcmZ3oR%O>Zm4+6^7N#xCY&p{fFRI#(2%6{I?snnt9X;itH@YC3dsO kw4cpk24WT@mSIEhiR{Z0-u5VHU=D-g47zmvnRkwi;t+Yg>+-+u5sN2NOen> Date: Thu, 31 Mar 2022 01:21:40 +1100 Subject: [PATCH 06/53] Fix typo in table 'client_relase' -> 'client_release' ( and other of the same typo ) (#703) * Fixed typo in table name 'client_relase' -> 'client_release'. Fixed more typos of the same typo. * Fixed migration ( but dirty lol ) --- api/scripts/droptables.sql | 2 +- api/src/routes/downloads.ts | 6 +++--- .../store/published-listings/applications.ts | 2 +- api/src/routes/store/published-listings/skus.ts | 2 +- api/src/routes/updates.ts | 12 ++++++------ bundle/package.json | 2 +- .../{ClientRelase.ts => ClientRelease.ts} | 4 ++-- util/src/entities/Config.ts | 10 +++++----- util/src/entities/index.ts | 2 +- util/src/migrations/1648643945733-ReleaseTypo.ts | 16 ++++++++++++++++ 10 files changed, 37 insertions(+), 21 deletions(-) rename util/src/entities/{ClientRelase.ts => ClientRelease.ts} (81%) create mode 100644 util/src/migrations/1648643945733-ReleaseTypo.ts diff --git a/api/scripts/droptables.sql b/api/scripts/droptables.sql index 57d1b2719..8a8520480 100644 --- a/api/scripts/droptables.sql +++ b/api/scripts/droptables.sql @@ -26,6 +26,6 @@ DROP TABLE webhooks; DROP TABLE channels; DROP TABLE members; DROP TABLE guilds; -DROP TABLE client_relase; +DROP TABLE client_release; -- DROP TABLE users; -- DROP TABLE config; \ No newline at end of file diff --git a/api/src/routes/downloads.ts b/api/src/routes/downloads.ts index ad78b62f5..ddfc080cf 100644 --- a/api/src/routes/downloads.ts +++ b/api/src/routes/downloads.ts @@ -1,6 +1,6 @@ import { Router, Response, Request } from "express"; import { route } from "@fosscord/api"; -import { Relase, Config } from "@fosscord/util"; +import { Release, Config } from "@fosscord/util"; const router = Router(); @@ -12,9 +12,9 @@ router.get("/:branch", route({}), async (req: Request, res: Response) => { if(!platform || !["linux", "osx", "win"].includes(platform.toString())) return res.status(404) - const relase = await Relase.findOneOrFail({ name: client.relases.upstreamVersion }); + const release = await Release.findOneOrFail({ name: client.releases.upstreamVersion }); - res.redirect(relase[`win_url`]); + res.redirect(release[`win_url`]); }); export default router; diff --git a/api/src/routes/store/published-listings/applications.ts b/api/src/routes/store/published-listings/applications.ts index f06a01e46..060a4c3de 100644 --- a/api/src/routes/store/published-listings/applications.ts +++ b/api/src/routes/store/published-listings/applications.ts @@ -18,7 +18,7 @@ router.get("/:id", route({}), async (req: Request, res: Response) => { access_type: 2, name: "", features: [], - relase_date: "", + release_date: "", premium: false, slug: "", flags: 4, diff --git a/api/src/routes/store/published-listings/skus.ts b/api/src/routes/store/published-listings/skus.ts index f06a01e46..060a4c3de 100644 --- a/api/src/routes/store/published-listings/skus.ts +++ b/api/src/routes/store/published-listings/skus.ts @@ -18,7 +18,7 @@ router.get("/:id", route({}), async (req: Request, res: Response) => { access_type: 2, name: "", features: [], - relase_date: "", + release_date: "", premium: false, slug: "", flags: 4, diff --git a/api/src/routes/updates.ts b/api/src/routes/updates.ts index 4682ce7cb..cb4577c8e 100644 --- a/api/src/routes/updates.ts +++ b/api/src/routes/updates.ts @@ -1,19 +1,19 @@ import { Router, Response, Request } from "express"; import { route } from "@fosscord/api"; -import { Config, Relase } from "@fosscord/util"; +import { Config, Release } from "@fosscord/util"; const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { const { client } = Config.get(); - const relase = await Relase.findOneOrFail({ name: client.relases.upstreamVersion}) + const release = await Release.findOneOrFail({ name: client.releases.upstreamVersion}) res.json({ - name: relase.name, - pub_date: relase.pub_date, - url: relase.url, - notes: relase.notes + name: release.name, + pub_date: release.pub_date, + url: release.url, + notes: release.notes }); }); diff --git a/bundle/package.json b/bundle/package.json index 3754a3bf4..7d68427fe 100644 --- a/bundle/package.json +++ b/bundle/package.json @@ -111,4 +111,4 @@ "typescript-json-schema": "^0.50.1", "ws": "^7.4.2" } -} +} \ No newline at end of file diff --git a/util/src/entities/ClientRelase.ts b/util/src/entities/ClientRelease.ts similarity index 81% rename from util/src/entities/ClientRelase.ts rename to util/src/entities/ClientRelease.ts index e021b82ba..c5afd3070 100644 --- a/util/src/entities/ClientRelase.ts +++ b/util/src/entities/ClientRelease.ts @@ -1,8 +1,8 @@ import { Column, Entity} from "typeorm"; import { BaseClass } from "./BaseClass"; -@Entity("client_relase") -export class Relase extends BaseClass { +@Entity("client_release") +export class Release extends BaseClass { @Column() name: string; diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts index f4a266dc4..8d29b387a 100644 --- a/util/src/entities/Config.ts +++ b/util/src/entities/Config.ts @@ -188,8 +188,8 @@ export interface ConfigValue { }, client: { useTestClient: Boolean; - relases: { - useLocalRelases: Boolean; //TODO + releases: { + useLocalRelease: Boolean; //TODO upstreamVersion: string; } }, @@ -222,7 +222,7 @@ export const DefaultConfigOptions: ConfigValue = { }, general: { instanceName: "Fosscord Instance", - instanceDescription: "This is a Fosscord instance made in pre-relase days", + instanceDescription: "This is a Fosscord instance made in pre-release days", frontPage: null, tosPage: null, correspondenceEmail: "noreply@localhost.local", @@ -389,8 +389,8 @@ export const DefaultConfigOptions: ConfigValue = { }, client: { useTestClient: true, - relases: { - useLocalRelases: true, + releases: { + useLocalRelease: true, upstreamVersion: "0.0.264" } }, diff --git a/util/src/entities/index.ts b/util/src/entities/index.ts index fc18d4220..f023d5a6b 100644 --- a/util/src/entities/index.ts +++ b/util/src/entities/index.ts @@ -27,4 +27,4 @@ export * from "./Template"; export * from "./User"; export * from "./VoiceState"; export * from "./Webhook"; -export * from "./ClientRelase"; \ No newline at end of file +export * from "./ClientRelease"; \ No newline at end of file diff --git a/util/src/migrations/1648643945733-ReleaseTypo.ts b/util/src/migrations/1648643945733-ReleaseTypo.ts new file mode 100644 index 000000000..944b9dd9e --- /dev/null +++ b/util/src/migrations/1648643945733-ReleaseTypo.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ReleaseTypo1648643945733 implements MigrationInterface { + name = "ReleaseTypo1648643945733"; + + public async up(queryRunner: QueryRunner): Promise { + //drop table first because typeorm creates it before migrations run + await queryRunner.dropTable("client_release", true); + await queryRunner.renameTable("client_relase", "client_release"); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropTable("client_relase", true); + await queryRunner.renameTable("client_release", "client_relase"); + } +} From 31bfe2a22a81b0878e9232d91b19925ff12d4007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 2 Apr 2022 10:22:54 +0300 Subject: [PATCH 07/53] =?UTF-8?q?first=20steps=20for=20E2EE=20support=20?= =?UTF-8?q?=E2=80=94=20channel=20security=20settings=20event?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/src/entities/Encryption.ts | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 util/src/entities/Encryption.ts diff --git a/util/src/entities/Encryption.ts b/util/src/entities/Encryption.ts new file mode 100644 index 000000000..3b82ff84b --- /dev/null +++ b/util/src/entities/Encryption.ts @@ -0,0 +1,35 @@ +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; +import { BaseClass } from "./BaseClass"; +import { Guild } from "./Guild"; +import { PublicUserProjection, User } from "./User"; +import { HTTPError } from "lambert-server"; +import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util"; +import { BitField, BitFieldResolvable, BitFlag } from "../util/BitField"; +import { Recipient } from "./Recipient"; +import { Message } from "./Message"; +import { ReadState } from "./ReadState"; +import { Invite } from "./Invite"; +import { DmChannelDTO } from "../dtos"; + +@Entity("security_settings") +export class SecuritySettings extends BaseClass { + + @Column({nullable: true}) + guild_id: Snowflake; + + @Column({nullable: true}) + channel_id: Snowflake; + + @Column() + encryption_permission_mask: BitField; + + @Column() + allowed_algorithms: string[]; + + @Column() + current_algorithm: string; + + @Column({nullable: true}) + used_since_message: Snowflake; + +} From 18aa4c405bab0ebf2c7dd1fd1d7e33475f764c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 2 Apr 2022 12:06:14 +0300 Subject: [PATCH 08/53] More message types --- util/src/entities/Message.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts index e577d5df9..04b047470 100644 --- a/util/src/entities/Message.ts +++ b/util/src/entities/Message.ts @@ -41,8 +41,14 @@ export enum MessageType { CHANNEL_FOLLOW_ADD = 12, GUILD_DISCOVERY_DISQUALIFIED = 14, GUILD_DISCOVERY_REQUALIFIED = 15, + ENCRYPTED = 16, REPLY = 19, APPLICATION_COMMAND = 20, + ROUTE_ADDED = 41, // custom message routing: new route affecting that channel + ROUTE_DISABLED = 42, // custom message routing: given route no longer affecting that channel + ENCRYPTION = 50, + CUSTOM_START = 63, + UNHANDLED = 255 } @Entity("messages") @@ -203,6 +209,7 @@ export interface MessageComponent { } export enum MessageComponentType { + Script = 0, // self command script ActionRow = 1, Button = 2, } From 1a3812a483f63c1f78b12a1e0182d139bc8af921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sun, 3 Apr 2022 14:49:16 +0300 Subject: [PATCH 09/53] Add our custom channel types --- util/src/entities/Channel.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index 08be1e02f..4bf819017 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -20,13 +20,17 @@ export enum ChannelType { GROUP_DM = 3, // a direct message between multiple users GUILD_CATEGORY = 4, // an organizational category that contains zero or more channels GUILD_NEWS = 5, // a channel that users can follow and crosspost into a guild or route - GUILD_STORE = 6, // a channel in which game developers can sell their game on Discord + GUILD_STORE = 6, // a channel in which game developers can sell their things ENCRYPTED = 7, // end-to-end encrypted channel ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel + TRANSACTIONAL = 9, // event chain style transactional channel GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience + TICKET_TRACKER = 33, // ticket tracker, individual ticket items shall have type 12 + KANBAN = 34, // confluence like kanban board + VOICELESS_WHITEBOARD = 35, // whiteboard but without voice (whiteboard + voice is the same as stage) CUSTOM_START = 64, // start custom channel types from here UNHANDLED = 255 // unhandled unowned pass-through channel type } From fac61d7f6a52145580c167c8f3394820604db512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Mon, 4 Apr 2022 18:22:37 +0300 Subject: [PATCH 10/53] Revert "Make member.premium_since ISO8601 timestamp" (#710) This reverts commit 093ae5558007031253b5dadb5a5be96dd265683d. --- util/src/entities/Member.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts index 928a25d72..a246b8917 100644 --- a/util/src/entities/Member.ts +++ b/util/src/entities/Member.ts @@ -85,8 +85,8 @@ export class Member extends BaseClassWithoutId { @Column() joined_at: Date; - @Column() - premium_since?: Date; + @Column({ type: "bigint", nullable: true }) + premium_since?: number; @Column() deaf: boolean; @@ -245,7 +245,7 @@ export class Member extends BaseClassWithoutId { nick: undefined, roles: [guild_id], // @everyone role joined_at: new Date(), - premium_since: new Date(), + premium_since: (new Date()).getTime(), deaf: false, mute: false, pending: false, From d08689b4180c2a66382ca9a6174b1c177076a65f Mon Sep 17 00:00:00 2001 From: Madeline <46743919+MaddyUnderStars@users.noreply.github.com> Date: Tue, 5 Apr 2022 19:58:34 +1000 Subject: [PATCH 11/53] User Notes (#707) * Notes implementation. Bug: Client does not save note locally after uploading to server. Client does save after reloading page. Is this due to the response being sent by PUT? * I don't know why the client doesn't do optimistic UI updates with this, or any updates at all without reloading the page * Added USER_NOTE_UPDATE event, thanks @TheRealGeoDash2019 ! --- api/src/routes/users/@me/notes.ts | 35 ++++++++++++++++++++++++++----- util/src/entities/User.ts | 4 ++++ util/src/interfaces/Event.ts | 1 + 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/api/src/routes/users/@me/notes.ts b/api/src/routes/users/@me/notes.ts index 96067bf5f..4887b1918 100644 --- a/api/src/routes/users/@me/notes.ts +++ b/api/src/routes/users/@me/notes.ts @@ -1,14 +1,39 @@ import { Request, Response, Router } from "express"; import { route } from "@fosscord/api"; +import { User, emitEvent } from "@fosscord/util"; const router: Router = Router(); +router.get("/:id", route({}), async (req: Request, res: Response) => { + const { id } = req.params; + const user = await User.findOneOrFail({ where: { id: req.user_id }, select: ["notes"] }); + + const note = user.notes[id]; + return res.json({ + note: note, + note_user_id: id, + user_id: user.id, + }); +}); + router.put("/:id", route({}), async (req: Request, res: Response) => { - //TODO - res.json({ - message: "Unknown User", - code: 10013 - }).status(404); + const { id } = req.params; + const user = await User.findOneOrFail({ where: { id: req.user_id } }); + const noteUser = await User.findOneOrFail({ where: { id: id }}); //if noted user does not exist throw + const { note } = req.body; + + await User.update({ id: req.user_id }, { notes: { ...user.notes, [noteUser.id]: note } }); + + await emitEvent({ + event: "USER_NOTE_UPDATE", + data: { + note: note, + id: noteUser.id + }, + user_id: user.id, + }) + + return res.status(204); }); export default router; diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index ed7bd4ce7..7091ee24b 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -164,6 +164,9 @@ export class User extends BaseClass { @Column({ type: "simple-json", select: false }) settings: UserSettings; + @Column({ type: "simple-json" }) + notes: { [key: string]: string }; //key is ID of user + toPublicUser() { const user: any = {}; PublicUserProjection.forEach((x) => { @@ -271,6 +274,7 @@ export class User extends BaseClass { }, settings: { ...defaultSettings, locale: language }, fingerprints: [], + notes: {}, }); await user.save(); diff --git a/util/src/interfaces/Event.ts b/util/src/interfaces/Event.ts index a5253c09c..416082eda 100644 --- a/util/src/interfaces/Event.ts +++ b/util/src/interfaces/Event.ts @@ -623,6 +623,7 @@ export type EVENT = | "PRESENCE_UPDATE" | "TYPING_START" | "USER_UPDATE" + | "USER_NOTE_UPDATE" | "WEBHOOKS_UPDATE" | "INTERACTION_CREATE" | "VOICE_STATE_UPDATE" From 3702c9c1670cb6716ba203eeb32080b226914f28 Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 4 Apr 2022 15:10:50 +0200 Subject: [PATCH 12/53] New translations common.json (Hebrew) --- api/locales/he/common.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api/locales/he/common.json b/api/locales/he/common.json index 8bb9c0421..9e72e9416 100644 --- a/api/locales/he/common.json +++ b/api/locales/he/common.json @@ -7,12 +7,12 @@ "BASE_TYPE_BOOLEAN": "This field must be a boolean", "BASE_TYPE_CHOICES": "This field must be one of ({{types}})", "BASE_TYPE_CLASS": "This field must be an instance of {{type}}", - "BASE_TYPE_OBJECT": "This field must be an object", - "BASE_TYPE_ARRAY": "This field must be an array", - "UNKOWN_FIELD": "Unknown key: {{key}}", - "BASE_TYPE_CONSTANT": "This field must be {{value}}", - "EMAIL_TYPE_INVALID_EMAIL": "Not a well-formed email address", - "DATE_TYPE_PARSE": "Could not parse {{date}}. Should be ISO8601", - "BASE_TYPE_BAD_LENGTH": "Must be between {{length}} in length" + "BASE_TYPE_OBJECT": "שדה זה חייב להיות אובייקט", + "BASE_TYPE_ARRAY": "שדה זה חייב להיות מערך", + "UNKOWN_FIELD": "מפתח לא ידוע: {{key}}", + "BASE_TYPE_CONSTANT": "שדה זה להיות {{value}}", + "EMAIL_TYPE_INVALID_EMAIL": "כתובת דואר אלקטרוני לא חוקית", + "DATE_TYPE_PARSE": "לא ניתן לנתח {{date}}. צריך להיות ISO8601", + "BASE_TYPE_BAD_LENGTH": "האורך חייב להיות בין {{length}}" } } From 9d753774094ffc85ad43307221a4aeb330f8e172 Mon Sep 17 00:00:00 2001 From: Luna Alfien Date: Wed, 6 Apr 2022 16:07:50 -0700 Subject: [PATCH 13/53] Fix 404 URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1bcea1e32..a15a4b641 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,6 @@ This repository contains: - [Contributing](https://docs.fosscord.com/contributing/server/) -## [Setup](https://docs.fosscord.com/setup/server/) +## [Setup](https://docs.fosscord.com/server/setup/) - [Download](https://github.com/fosscord/fosscord-server/releases) From f8bb47508659a58faa222ef42fd61f64016f94d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Thu, 7 Apr 2022 17:49:44 +0300 Subject: [PATCH 14/53] with public read receipts explicitly stored, no need to store manual flag of the read mark --- util/src/entities/ReadState.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/src/entities/ReadState.ts b/util/src/entities/ReadState.ts index e6d731053..b915573b8 100644 --- a/util/src/entities/ReadState.ts +++ b/util/src/entities/ReadState.ts @@ -49,6 +49,7 @@ export class ReadState extends BaseClass { @Column({ nullable: true }) mention_count: number; - @Column({ nullable: true }) + // @Column({ nullable: true }) + // TODO: derive this from (last_message_id=notifications_cursor=public_ack)=true manual: boolean; } From 742e534e31e332ecf49ea5aacc734ef52958bd20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Thu, 7 Apr 2022 23:13:43 +0300 Subject: [PATCH 15/53] scheduled maintenances --- .../routes/scheduled-maintenances/upcoming_json.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 api/src/routes/scheduled-maintenances/upcoming_json.ts diff --git a/api/src/routes/scheduled-maintenances/upcoming_json.ts b/api/src/routes/scheduled-maintenances/upcoming_json.ts new file mode 100644 index 000000000..83092e44c --- /dev/null +++ b/api/src/routes/scheduled-maintenances/upcoming_json.ts @@ -0,0 +1,12 @@ +import { Router, Request, Response } from "express"; +import { route } from "@fosscord/api"; +const router = Router(); + +router.get("/scheduled-maintenances/upcoming.json",route({}), async (req: Request, res: Response) => { + res.json({ + "page": {}, + "scheduled_maintenances": {} + }); +}); + +export default router; From c5de68d0bc24c939987060ce593ddb1182c3df74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Thu, 7 Apr 2022 23:15:41 +0300 Subject: [PATCH 16/53] added the maintenance listing endpoint --- api/src/middlewares/Authentication.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/api/src/middlewares/Authentication.ts b/api/src/middlewares/Authentication.ts index 429cf11eb..5a08caf32 100644 --- a/api/src/middlewares/Authentication.ts +++ b/api/src/middlewares/Authentication.ts @@ -15,6 +15,7 @@ export const NO_AUTHORIZATION_ROUTES = [ "/experiments", "/updates", "/downloads/", + "/scheduled-maintenances/upcoming.json", // Public kubernetes integration "/-/readyz", "/-/healthz", From d1f24b25370203a7604853727dc535eb87c21122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Thu, 7 Apr 2022 23:47:26 +0300 Subject: [PATCH 17/53] More rights stuff --- util/src/util/Rights.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/util/src/util/Rights.ts b/util/src/util/Rights.ts index db5384d03..dedbfe300 100644 --- a/util/src/util/Rights.ts +++ b/util/src/util/Rights.ts @@ -1,6 +1,7 @@ import { BitField } from "./BitField"; import "missing-native-js-functions"; import { BitFieldResolvable, BitFlag } from "./BitField"; +import { User } from "../entities"; var HTTPError: any; @@ -85,6 +86,16 @@ export class Rights extends BitField { // @ts-ignore throw new HTTPError(`You are missing the following rights ${permission}`, 403); } + + export async function getRight( + user_id: string, + /** opts: { + in_behalf?: (keyof User)[]; + } = {} **/) + { + user = await User.findOneOrFail({ where: { id: user_id } }); + return new Rights(user.right); + } } const ALL_RIGHTS = Object.values(Rights.FLAGS).reduce((total, val) => total | val, BigInt(0)); From 785544e1c8d7b579f161c0b3ca0c6e13e44cae18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 00:00:22 +0300 Subject: [PATCH 18/53] Update index.ts --- .../#channel_id/messages/#message_id/index.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts index 7f7de264a..bdc34a81e 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts @@ -1,4 +1,4 @@ -import { Channel, emitEvent, getPermission, MessageDeleteEvent, Message, MessageUpdateEvent } from "@fosscord/util"; +import { Channel, emitEvent, getPermission, getRight MessageDeleteEvent, Message, MessageUpdateEvent } from "@fosscord/util"; import { Router, Response, Request } from "express"; import { route } from "@fosscord/api"; import { handleMessage, postHandleMessage } from "@fosscord/api"; @@ -7,18 +7,21 @@ import { MessageCreateSchema } from "../index"; const router = Router(); // TODO: message content/embed string length limit -router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES" }), async (req: Request, res: Response) => { +router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES" }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; var body = req.body as MessageCreateSchema; const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] }); const permissions = await getPermission(req.user_id, undefined, channel_id); + + const rights = await getRights(req.user_id); - if (req.user_id !== message.author_id) { + if ((req.user_id !== message.author_id)) { + if (rights.has("MANAGE_MESSAGES")) break; permissions.hasThrow("MANAGE_MESSAGES"); body = { flags: body.flags }; // admins can only suppress embeds of other messages - } + } else rights.hasThrow("SELF_EDIT_MESSAGES"); const new_message = await handleMessage({ ...message, @@ -46,17 +49,17 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE return res.json(message); }); -// permission check only if deletes messagr from other user router.delete("/", route({}), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; const channel = await Channel.findOneOrFail({ id: channel_id }); const message = await Message.findOneOrFail({ id: message_id }); - if (message.author_id !== req.user_id) { + if ((message.author_id !== req.user_id)) { + if (rights.has("MANAGE_MESSAGES")) break; const permission = await getPermission(req.user_id, channel.guild_id, channel_id); permission.hasThrow("MANAGE_MESSAGES"); - } + } else rights.hasThrow("SELF_DELETE_MESSAGES"); await Message.delete({ id: message_id }); From ec07a9f415eb34eac2249c9fdaf0769f880717d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 10:26:20 +0300 Subject: [PATCH 19/53] fix the build mistakes from yesternight --- .../#channel_id/messages/#message_id/index.ts | 19 ++++++++++++------- util/src/util/Rights.ts | 17 ++++++++--------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts index bdc34a81e..58dfb1cc1 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts @@ -1,4 +1,4 @@ -import { Channel, emitEvent, getPermission, getRight MessageDeleteEvent, Message, MessageUpdateEvent } from "@fosscord/util"; +import { Channel, emitEvent, getPermission, getRights, MessageDeleteEvent, Message, MessageUpdateEvent } from "@fosscord/util"; import { Router, Response, Request } from "express"; import { route } from "@fosscord/api"; import { handleMessage, postHandleMessage } from "@fosscord/api"; @@ -18,9 +18,11 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE const rights = await getRights(req.user_id); if ((req.user_id !== message.author_id)) { - if (rights.has("MANAGE_MESSAGES")) break; - permissions.hasThrow("MANAGE_MESSAGES"); - body = { flags: body.flags }; // admins can only suppress embeds of other messages + if (!rights.has("MANAGE_MESSAGES")) { + permissions.hasThrow("MANAGE_MESSAGES"); + body = { flags: body.flags }; +// guild admins can only suppress embeds of other messages, no such restriction imposed to instance-wide admins + } } else rights.hasThrow("SELF_EDIT_MESSAGES"); const new_message = await handleMessage({ @@ -54,11 +56,14 @@ router.delete("/", route({}), async (req: Request, res: Response) => { const channel = await Channel.findOneOrFail({ id: channel_id }); const message = await Message.findOneOrFail({ id: message_id }); + + const rights = await getRights(req.user_id); if ((message.author_id !== req.user_id)) { - if (rights.has("MANAGE_MESSAGES")) break; - const permission = await getPermission(req.user_id, channel.guild_id, channel_id); - permission.hasThrow("MANAGE_MESSAGES"); + if (!rights.has("MANAGE_MESSAGES")) { + const permission = await getPermission(req.user_id, channel.guild_id, channel_id); + permission.hasThrow("MANAGE_MESSAGES"); + } } else rights.hasThrow("SELF_DELETE_MESSAGES"); await Message.delete({ id: message_id }); diff --git a/util/src/util/Rights.ts b/util/src/util/Rights.ts index dedbfe300..35ad9514f 100644 --- a/util/src/util/Rights.ts +++ b/util/src/util/Rights.ts @@ -87,15 +87,14 @@ export class Rights extends BitField { throw new HTTPError(`You are missing the following rights ${permission}`, 403); } - export async function getRight( - user_id: string, - /** opts: { - in_behalf?: (keyof User)[]; - } = {} **/) - { - user = await User.findOneOrFail({ where: { id: user_id } }); - return new Rights(user.right); - } } const ALL_RIGHTS = Object.values(Rights.FLAGS).reduce((total, val) => total | val, BigInt(0)); + +export async function getRights( user_id: string + /**, opts: { + in_behalf?: (keyof User)[]; + } = {} **/) { + let user = await User.findOneOrFail({ where: { id: user_id } }); + return new Rights(user.rights); +} From 5774c037eedba9f7c05d66f86f350a0a480f82a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 10:53:05 +0300 Subject: [PATCH 20/53] add joined_by to allow for separate treatment of force-joiners --- util/src/entities/Member.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts index a246b8917..ae889a852 100644 --- a/util/src/entities/Member.ts +++ b/util/src/entities/Member.ts @@ -70,7 +70,7 @@ export class Member extends BaseClassWithoutId { @Column({ nullable: true }) nick?: string; - + @JoinTable({ name: "member_roles", joinColumn: { name: "index", referencedColumnName: "index" }, @@ -102,8 +102,17 @@ export class Member extends BaseClassWithoutId { @Column({ nullable: true }) last_message_id?: string; + + /** + @JoinColumn({ name: "id" }) + @ManyToOne(() => User, { + onDelete: "DO NOTHING", + // do not auto-kick force-joined members just because their joiners left the server + }) **/ + @Column({ nullable: true }) + joined_by: string; - // TODO: update + // TODO: add this when we have proper read receipts // @Column({ type: "simple-json" }) // read_state: ReadState; From 68d1b6efd20d9c666e86326c4437f113809a6d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 10:53:49 +0300 Subject: [PATCH 21/53] optional --- util/src/entities/Member.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts index ae889a852..fe2d5590a 100644 --- a/util/src/entities/Member.ts +++ b/util/src/entities/Member.ts @@ -109,8 +109,8 @@ export class Member extends BaseClassWithoutId { onDelete: "DO NOTHING", // do not auto-kick force-joined members just because their joiners left the server }) **/ - @Column({ nullable: true }) - joined_by: string; + @Column({ nullable: true}) + joined_by?: string; // TODO: add this when we have proper read receipts // @Column({ type: "simple-json" }) From 22952ef928808d4112e0bd3c2a5b867d3e4c4b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 11:02:11 +0300 Subject: [PATCH 22/53] enforce the rights --- api/src/util/handlers/Message.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/api/src/util/handlers/Message.ts b/api/src/util/handlers/Message.ts index 2d9f70325..f0ecf416c 100644 --- a/api/src/util/handlers/Message.ts +++ b/api/src/util/handlers/Message.ts @@ -7,6 +7,7 @@ import { MessageCreateEvent, MessageUpdateEvent, getPermission, + getRights, CHANNEL_MENTION, Snowflake, USER_MENTION, @@ -61,17 +62,18 @@ export async function handleMessage(opts: MessageOptions): Promise { throw new HTTPError("Content length over max character limit") } - // TODO: are tts messages allowed in dm channels? should permission be checked? if (opts.author_id) { message.author = await User.getPublicUser(opts.author_id); - } + const rights = await getRights(opts.author_id); + rights.hasThrow("SEND_MESSAGES"); + } if (opts.application_id) { message.application = await Application.findOneOrFail({ id: opts.application_id }); } if (opts.webhook_id) { message.webhook = await Webhook.findOneOrFail({ id: opts.webhook_id }); } - + const permission = await getPermission(opts.author_id, channel.guild_id, opts.channel_id); permission.hasThrow("SEND_MESSAGES"); // TODO: add the rights check if (permission.cache.member) { From be3f796f3462ce925c445d710e848425ac1f9d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 11:05:19 +0300 Subject: [PATCH 23/53] remove todos that are implemented --- api/src/util/handlers/Message.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/util/handlers/Message.ts b/api/src/util/handlers/Message.ts index f0ecf416c..5a5ac6665 100644 --- a/api/src/util/handlers/Message.ts +++ b/api/src/util/handlers/Message.ts @@ -75,7 +75,7 @@ export async function handleMessage(opts: MessageOptions): Promise { } const permission = await getPermission(opts.author_id, channel.guild_id, opts.channel_id); - permission.hasThrow("SEND_MESSAGES"); // TODO: add the rights check + permission.hasThrow("SEND_MESSAGES"); if (permission.cache.member) { message.member = permission.cache.member; } @@ -83,7 +83,7 @@ export async function handleMessage(opts: MessageOptions): Promise { if (opts.tts) permission.hasThrow("SEND_TTS_MESSAGES"); if (opts.message_reference) { permission.hasThrow("READ_MESSAGE_HISTORY"); - // code below has to be redone when we add custom message routing and cross-channel replies + // code below has to be redone when we add custom message routing if (message.guild_id !== null) { const guild = await Guild.findOneOrFail({ id: channel.guild_id }); if (!guild.features.includes("CROSS_CHANNEL_REPLIES")) { @@ -91,7 +91,7 @@ export async function handleMessage(opts: MessageOptions): Promise { if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel"); } } - // TODO: should be checked if the referenced message exists? + // Q: should be checked if the referenced message exists? ANSWER: NO // @ts-ignore message.type = MessageType.REPLY; } From 3a5a90007e7ad8942cd121cf410f7996ecb1e35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 11:23:09 +0300 Subject: [PATCH 24/53] MANAGE_GUILDS --- api/src/routes/guilds/#guild_id/index.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts index 991c3f932..8e1e74f79 100644 --- a/api/src/routes/guilds/#guild_id/index.ts +++ b/api/src/routes/guilds/#guild_id/index.ts @@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { emitEvent, getPermission, Guild, GuildUpdateEvent, handleFile, Member } from "@fosscord/util"; +import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpdateEvent, handleFile, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { route } from "@fosscord/api"; import "missing-native-js-functions"; @@ -37,9 +37,17 @@ router.get("/", route({}), async (req: Request, res: Response) => { return res.send(guild); }); -router.patch("/", route({ body: "GuildUpdateSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { +router.patch("/", route({ body: "GuildUpdateSchema"}), async (req: Request, res: Response) => { const body = req.body as GuildUpdateSchema; const { guild_id } = req.params; + + + const rights = await getRight(req.user_id); + const permission = await getPermission(req.user_id, guild_id); + + if (!rights.has("MANAGE_GUILDS")||!permission.has("MANAGE_GUILD")) + throw DiscordApiErrors.MISSING_PERMISSIONS("MANAGE_GUILD"); + // TODO: guild update check image if (body.icon) body.icon = await handleFile(`/icons/${guild_id}`, body.icon); From a4e4d40bb967a73130363b134cf9072e08ea4d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 11:29:04 +0300 Subject: [PATCH 25/53] rights enforcement in guild create --- api/src/routes/guilds/index.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts index 7b6762112..10721413f 100644 --- a/api/src/routes/guilds/index.ts +++ b/api/src/routes/guilds/index.ts @@ -1,5 +1,5 @@ import { Router, Request, Response } from "express"; -import { Role, Guild, Snowflake, Config, Member, Channel, DiscordApiErrors, handleFile } from "@fosscord/util"; +import { Role, Guild, Snowflake, Config, getRights, Member, Channel, DiscordApiErrors, handleFile } from "@fosscord/util"; import { route } from "@fosscord/api"; import { ChannelModifySchema } from "../channels/#channel_id"; @@ -20,12 +20,13 @@ export interface GuildCreateSchema { //TODO: create default channel -router.post("/", route({ body: "GuildCreateSchema" }), async (req: Request, res: Response) => { +router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), async (req: Request, res: Response) => { const body = req.body as GuildCreateSchema; const { maxGuilds } = Config.get().limits.user; const guild_count = await Member.count({ id: req.user_id }); - if (guild_count >= maxGuilds) { + const rights = await getRights(req.user_id); + if ((guild_count >= maxGuilds)&&!rights.has("MANAGE_GUILDS")) { throw DiscordApiErrors.MAXIMUM_GUILDS.withParams(maxGuilds); } From 76268ae456f9151250a762dd1dc9cec7a127889a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 11:32:00 +0300 Subject: [PATCH 26/53] JOIN_GUILDS --- api/src/routes/invites/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/routes/invites/index.ts b/api/src/routes/invites/index.ts index 37e9e05a3..21da2d184 100644 --- a/api/src/routes/invites/index.ts +++ b/api/src/routes/invites/index.ts @@ -13,7 +13,7 @@ router.get("/:code", route({}), async (req: Request, res: Response) => { res.status(200).send(invite); }); -router.post("/:code", route({}), async (req: Request, res: Response) => { +router.post("/:code", route({right: "JOIN_GUILDS"}), async (req: Request, res: Response) => { const { code } = req.params; const { guild_id } = await Invite.findOneOrFail({ code }) const { features } = await Guild.findOneOrFail({ id: guild_id}); From 2c0d2f40c8df354c5a749e9af647aba4066e45b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 11:34:01 +0300 Subject: [PATCH 27/53] invite right enforced --- api/src/routes/channels/#channel_id/invites.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts index 6d2c625d5..208a0705a 100644 --- a/api/src/routes/channels/#channel_id/invites.ts +++ b/api/src/routes/channels/#channel_id/invites.ts @@ -19,7 +19,8 @@ export interface InviteCreateSchema { target_user_type?: number; } -router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE" }), async (req: Request, res: Response) => { +router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INSTANT_INVITE" }), + async (req: Request, res: Response) => { const { user_id } = req; const { channel_id } = req.params; const channel = await Channel.findOneOrFail({ where: { id: channel_id }, select: ["id", "name", "type", "guild_id"] }); From 271574bb384a4d8a08f0058a453abd7839707b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Fri, 8 Apr 2022 17:30:55 +0300 Subject: [PATCH 28/53] correct right name --- api/src/routes/channels/#channel_id/invites.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts index 208a0705a..6367a8b6e 100644 --- a/api/src/routes/channels/#channel_id/invites.ts +++ b/api/src/routes/channels/#channel_id/invites.ts @@ -19,7 +19,7 @@ export interface InviteCreateSchema { target_user_type?: number; } -router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INSTANT_INVITE" }), +router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INVITES", right: "CREATE_INSTANT_INVITE" }), async (req: Request, res: Response) => { const { user_id } = req; const { channel_id } = req.params; From 596c60e010a8372c729306476c0734e86f990ad9 Mon Sep 17 00:00:00 2001 From: binsky Date: Sat, 9 Apr 2022 04:11:10 +0200 Subject: [PATCH 29/53] fix invite right enforcement --- api/src/routes/channels/#channel_id/invites.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts index 6367a8b6e..9c3611647 100644 --- a/api/src/routes/channels/#channel_id/invites.ts +++ b/api/src/routes/channels/#channel_id/invites.ts @@ -19,7 +19,7 @@ export interface InviteCreateSchema { target_user_type?: number; } -router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INVITES", right: "CREATE_INSTANT_INVITE" }), +router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INVITES" }), async (req: Request, res: Response) => { const { user_id } = req; const { channel_id } = req.params; From 88dd33a9a271ec73f9ce0beb8c5c8e662912fc68 Mon Sep 17 00:00:00 2001 From: binsky Date: Sat, 9 Apr 2022 04:12:16 +0200 Subject: [PATCH 30/53] fix MANAGE_GUILDS; rename getRight to getRights --- api/src/routes/guilds/#guild_id/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts index 8e1e74f79..4ec3df729 100644 --- a/api/src/routes/guilds/#guild_id/index.ts +++ b/api/src/routes/guilds/#guild_id/index.ts @@ -42,11 +42,11 @@ router.patch("/", route({ body: "GuildUpdateSchema"}), async (req: Request, res: const { guild_id } = req.params; - const rights = await getRight(req.user_id); + const rights = await getRights(req.user_id); const permission = await getPermission(req.user_id, guild_id); if (!rights.has("MANAGE_GUILDS")||!permission.has("MANAGE_GUILD")) - throw DiscordApiErrors.MISSING_PERMISSIONS("MANAGE_GUILD"); + throw DiscordApiErrors.MISSING_PERMISSIONS.withParams("MANAGE_GUILD"); // TODO: guild update check image From 66609ec5f49ad0fa3522a9ff0f340b7f61dcd9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 9 Apr 2022 13:46:50 +0300 Subject: [PATCH 31/53] Update User.ts --- util/src/entities/User.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index 7091ee24b..42d926b2f 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -60,7 +60,7 @@ export class User extends BaseClass { username: string; // username max length 32, min 2 (should be configurable) @Column() - discriminator: string; // #0001 4 digit long string from #0001 - #9999 + discriminator: string; // opaque string: 4 digits on discord.com setDiscriminator(val: string) { const number = Number(val); @@ -88,10 +88,10 @@ export class User extends BaseClass { mobile: boolean; // if the user has mobile app installed @Column() - premium: boolean; // if user bought nitro - + premium: boolean; // if user bought individual premium + @Column() - premium_type: number; // nitro level + premium_type: number; // individual premium level @Column() bot: boolean; // if user is bot @@ -100,11 +100,11 @@ export class User extends BaseClass { bio: string; // short description of the user (max 190 chars -> should be configurable) @Column() - system: boolean; // shouldn't be used, the api sents this field type true, if the generated message comes from a system generated author + system: boolean; // shouldn't be used, the api sends this field type true, if the generated message comes from a system generated author @Column({ select: false }) - nsfw_allowed: boolean; // if the user is older than 18 (resp. Config) - + nsfw_allowed: boolean; // if the user can do age-restricted actions (NSFW channels/guilds/commands) + @Column({ select: false }) mfa_enabled: boolean; // if multi factor authentication is enabled From 467f2d6ed934543360c4381e0e7052996773b909 Mon Sep 17 00:00:00 2001 From: Madeline <46743919+MaddyUnderStars@users.noreply.github.com> Date: Sat, 9 Apr 2022 23:53:57 +1000 Subject: [PATCH 32/53] Resolves #715 --- util/src/entities/User.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index 42d926b2f..a5c4c136a 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -132,7 +132,7 @@ export class User extends BaseClass { @Column() public_flags: number; - @Column() + @Column({ type: "bigint" }) rights: string; // Rights @OneToMany(() => Session, (session: Session) => session.user) From d54fa9b1cb6e5a35b44860565cd9592c22f121de Mon Sep 17 00:00:00 2001 From: 1itt1eB0y Date: Sat, 9 Apr 2022 22:43:38 +0800 Subject: [PATCH 33/53] bug fix Fix `QueryFailedError: constraint "FK_05535bc695e9f7ee104616459d3" for relation "messages" already exists` --- util/src/entities/Message.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts index 04b047470..b32bbd949 100644 --- a/util/src/entities/Message.ts +++ b/util/src/entities/Message.ts @@ -90,7 +90,7 @@ export class Message extends BaseClass { @RelationId((message: Message) => message.member) member_id: string; - @JoinColumn({ name: "author_id", referencedColumnName: "id" }) + @JoinColumn({ name: "member_id", referencedColumnName: "id" }) @ManyToOne(() => User, { onDelete: "CASCADE", }) From 2e6599654046291832b7138e452777e75d45f4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 9 Apr 2022 21:45:45 +0300 Subject: [PATCH 34/53] add an elegant entropy check --- api/src/util/utility/passwordStrength.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/api/src/util/utility/passwordStrength.ts b/api/src/util/utility/passwordStrength.ts index 047df008c..81ac2559c 100644 --- a/api/src/util/utility/passwordStrength.ts +++ b/api/src/util/utility/passwordStrength.ts @@ -13,6 +13,7 @@ const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored * - min numbers * - min symbols * - min uppercase chars + * - shannon entropy divided by password entropy * * Returns: 0 > pw > 1 */ @@ -22,28 +23,38 @@ export function checkPassword(password: string): number { // checks for total password len if (password.length >= minLength - 1) { - strength += 0.25; + strength += 0.05; } // checks for amount of Numbers if (password.count(reNUMBER) >= minNumbers - 1) { - strength += 0.25; + strength += 0.05; } // checks for amount of Uppercase Letters if (password.count(reUPPERCASELETTER) >= minUpperCase - 1) { - strength += 0.25; + strength += 0.05; } // checks for amount of symbols if (password.replace(reSYMBOLS, "").length >= minSymbols - 1) { - strength += 0.25; + strength += 0.05; } // checks if password only consists of numbers or only consists of chars if (password.length == password.count(reNUMBER) || password.length === password.count(reUPPERCASELETTER)) { strength = 0; } - + + var entropyMap; + for (let i = 0; i < password.length; i++) { + if (entropyMap[password[i]]) entropyMap[password[i]]++; + else entropyMap[password[i]] = 1; + } + + let entropies = Array(entropyMap); + + entropies.map(x => (x / entropyMap.length)); + strength += entropies.reduceRight((a, x), a - (x * Math.log2(x))) / Math.log2(password.length); return strength; } From fd702100ea5a9a88131b387f8ea573a601a1b3ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 9 Apr 2022 21:48:25 +0300 Subject: [PATCH 35/53] Update passwordStrength.ts --- api/src/util/utility/passwordStrength.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/util/utility/passwordStrength.ts b/api/src/util/utility/passwordStrength.ts index 81ac2559c..e75e48f6f 100644 --- a/api/src/util/utility/passwordStrength.ts +++ b/api/src/util/utility/passwordStrength.ts @@ -46,7 +46,7 @@ export function checkPassword(password: string): number { strength = 0; } - var entropyMap; + let entropyMap; for (let i = 0; i < password.length; i++) { if (entropyMap[password[i]]) entropyMap[password[i]]++; else entropyMap[password[i]] = 1; From 01315087d99b8f1d1c31bf83c363130376192f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sun, 10 Apr 2022 13:54:05 +0300 Subject: [PATCH 36/53] Update Guild.ts --- util/src/entities/Guild.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts index 9ac148ee3..70bb41c5d 100644 --- a/util/src/entities/Guild.ts +++ b/util/src/entities/Guild.ts @@ -187,11 +187,11 @@ export class Guild extends BaseClass { @Column({ nullable: true }) @RelationId((guild: Guild) => guild.owner) - owner_id: string; + owner_id?: string; // optional to allow for ownerless guilds @JoinColumn({ name: "owner_id", referencedColumnName: "id" }) @ManyToOne(() => User) - owner: User; + owner?: User; // optional to allow for ownerless guilds @Column({ nullable: true }) preferred_locale?: string; @@ -200,7 +200,7 @@ export class Guild extends BaseClass { premium_subscription_count?: number; @Column({ nullable: true }) - premium_tier?: number; // nitro boost level + premium_tier?: number; // crowd premium level @Column({ nullable: true }) @RelationId((guild: Guild) => guild.public_updates_channel) @@ -269,6 +269,10 @@ export class Guild extends BaseClass { @Column({ nullable: true }) nsfw?: boolean; + + // TODO: nested guilds + @Column({ nullable: true }) + parent?: string; // only for developer portal permissions?: number; @@ -308,7 +312,7 @@ export class Guild extends BaseClass { verification_level: 0, welcome_screen: { enabled: false, - description: "No description", + description: "Fill in your description", welcome_channels: [], }, widget_enabled: true, // NB: don't set it as false to prevent artificial restrictions From 977861ad4e6eff025f0c0a1b4731f0efd283886d Mon Sep 17 00:00:00 2001 From: Madeline <46743919+MaddyUnderStars@users.noreply.github.com> Date: Mon, 11 Apr 2022 00:36:12 +1000 Subject: [PATCH 37/53] Fix compile errors in checkPassword's entropy check --- api/src/util/utility/passwordStrength.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/util/utility/passwordStrength.ts b/api/src/util/utility/passwordStrength.ts index e75e48f6f..f3960e489 100644 --- a/api/src/util/utility/passwordStrength.ts +++ b/api/src/util/utility/passwordStrength.ts @@ -46,15 +46,15 @@ export function checkPassword(password: string): number { strength = 0; } - let entropyMap; + let entropyMap: { [key: string]: number } = {}; for (let i = 0; i < password.length; i++) { if (entropyMap[password[i]]) entropyMap[password[i]]++; else entropyMap[password[i]] = 1; } - let entropies = Array(entropyMap); - + let entropies = Object.values(entropyMap); + entropies.map(x => (x / entropyMap.length)); - strength += entropies.reduceRight((a, x), a - (x * Math.log2(x))) / Math.log2(password.length); + strength += entropies.reduceRight((a: number, x: number) => a - (x * Math.log2(x))) / Math.log2(password.length); return strength; } From 0aa100c8e079c60dfee2524ba70775ef276d930f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Tue, 12 Apr 2022 20:10:30 +0300 Subject: [PATCH 38/53] Update passwordStrength.ts --- api/src/util/utility/passwordStrength.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/util/utility/passwordStrength.ts b/api/src/util/utility/passwordStrength.ts index f3960e489..439700d04 100644 --- a/api/src/util/utility/passwordStrength.ts +++ b/api/src/util/utility/passwordStrength.ts @@ -13,7 +13,7 @@ const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored * - min numbers * - min symbols * - min uppercase chars - * - shannon entropy divided by password entropy + * - shannon entropy folded into [0, 1) interval * * Returns: 0 > pw > 1 */ From 8a67720fd0d3405e50f7357312e0b3bed87884d4 Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Tue, 12 Apr 2022 20:29:28 +0200 Subject: [PATCH 39/53] New translations auth.json (Swedish) --- api/locales/sv/auth.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/api/locales/sv/auth.json b/api/locales/sv/auth.json index e19547a01..04e557527 100644 --- a/api/locales/sv/auth.json +++ b/api/locales/sv/auth.json @@ -1,16 +1,16 @@ { "login": { - "INVALID_LOGIN": "E-Mail or Phone not found", - "INVALID_PASSWORD": "Invalid Password", - "ACCOUNT_DISABLED": "This account is disabled" + "INVALID_LOGIN": "E-post eller telefon hittades inte", + "INVALID_PASSWORD": "Ogiltigt lösenord", + "ACCOUNT_DISABLED": "Detta konto är inaktiverat" }, "register": { - "REGISTRATION_DISABLED": "New user registration is disabled", - "INVITE_ONLY": "You must be invited to register", - "EMAIL_INVALID": "Invalid Email", - "EMAIL_ALREADY_REGISTERED": "Email is already registered", - "DATE_OF_BIRTH_UNDERAGE": "You need to be {{years}} years or older", - "CONSENT_REQUIRED": "You must agree to the Terms of Service and Privacy Policy.", - "USERNAME_TOO_MANY_USERS": "Too many users have this username, please try another" + "REGISTRATION_DISABLED": "Registrering av nya användare är inaktiverat", + "INVITE_ONLY": "Du måste vara inbjuden för att registrera dig", + "EMAIL_INVALID": "Ogiltig e-post", + "EMAIL_ALREADY_REGISTERED": "E-postadressen är redan registrerad", + "DATE_OF_BIRTH_UNDERAGE": "Du måste vara {{years}} år eller äldre", + "CONSENT_REQUIRED": "Du måste godkänna användarvillkoren och sekretesspolicyn.", + "USERNAME_TOO_MANY_USERS": "För många användare har detta användarnamn, försök med ett annat" } } From 100e93a4ce1c579a0548762c0cef3aa546160133 Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Tue, 12 Apr 2022 20:29:30 +0200 Subject: [PATCH 40/53] New translations common.json (Swedish) --- api/locales/sv/common.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/api/locales/sv/common.json b/api/locales/sv/common.json index 8bb9c0421..56c02a643 100644 --- a/api/locales/sv/common.json +++ b/api/locales/sv/common.json @@ -1,18 +1,18 @@ { "field": { - "BASE_TYPE_REQUIRED": "This field is required", - "BASE_TYPE_STRING": "This field must be a string", - "BASE_TYPE_NUMBER": "This field must be a number", - "BASE_TYPE_BIGINT": "This field must be a bigint", - "BASE_TYPE_BOOLEAN": "This field must be a boolean", - "BASE_TYPE_CHOICES": "This field must be one of ({{types}})", - "BASE_TYPE_CLASS": "This field must be an instance of {{type}}", - "BASE_TYPE_OBJECT": "This field must be an object", - "BASE_TYPE_ARRAY": "This field must be an array", - "UNKOWN_FIELD": "Unknown key: {{key}}", - "BASE_TYPE_CONSTANT": "This field must be {{value}}", - "EMAIL_TYPE_INVALID_EMAIL": "Not a well-formed email address", - "DATE_TYPE_PARSE": "Could not parse {{date}}. Should be ISO8601", - "BASE_TYPE_BAD_LENGTH": "Must be between {{length}} in length" + "BASE_TYPE_REQUIRED": "Detta fältet krävs", + "BASE_TYPE_STRING": "Detta fält måste vara en sträng", + "BASE_TYPE_NUMBER": "Detta fält måste vara ett nummer", + "BASE_TYPE_BIGINT": "Detta fält måste vara av typen bigint", + "BASE_TYPE_BOOLEAN": "Detta fält måste vara booleskt", + "BASE_TYPE_CHOICES": "Detta fält måste vara av typen av ett av följande ({{types}})", + "BASE_TYPE_CLASS": "Det här fältet måste vara en instans av {{type}}", + "BASE_TYPE_OBJECT": "Detta fält måste vara ett objekt", + "BASE_TYPE_ARRAY": "Detta fält måste vara en array", + "UNKOWN_FIELD": "Okänd nyckel: {{key}}", + "BASE_TYPE_CONSTANT": "Det här fältet måste vara {{value}}", + "EMAIL_TYPE_INVALID_EMAIL": "E-postadressen har inte korrekt format", + "DATE_TYPE_PARSE": "Kunde inte tolka {{date}}. Bör vara ISO8601", + "BASE_TYPE_BAD_LENGTH": "Måste vara mellan {{length}} i längd" } } From bb09ba3f7fcd870ba34703c34239e1a39adc3c63 Mon Sep 17 00:00:00 2001 From: Kuna <65683493+kunamech@users.noreply.github.com> Date: Thu, 14 Apr 2022 19:28:46 +0300 Subject: [PATCH 41/53] Align buttons to center --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a15a4b641..f2743ed18 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

Fosscord Server

-

+

From 221f627f187e544159db38cf157a43369b3a98b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 16 Apr 2022 00:15:09 +0300 Subject: [PATCH 42/53] remove misleading todo note --- api/src/routes/guilds/#guild_id/members/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/api/src/routes/guilds/#guild_id/members/index.ts b/api/src/routes/guilds/#guild_id/members/index.ts index 386276c8b..b730a4e77 100644 --- a/api/src/routes/guilds/#guild_id/members/index.ts +++ b/api/src/routes/guilds/#guild_id/members/index.ts @@ -6,7 +6,6 @@ import { HTTPError } from "lambert-server"; const router = Router(); -// TODO: not allowed for user -> only allowed for bots with privileged intents // TODO: send over websocket // TODO: check for GUILD_MEMBERS intent From 57ed3cb5997d288fa158d5ed8090eb3b868f74a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 16 Apr 2022 00:20:24 +0300 Subject: [PATCH 43/53] add more intents --- util/src/util/Intents.ts | 41 +++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/util/src/util/Intents.ts b/util/src/util/Intents.ts index 943b29cf6..8b8915a19 100644 --- a/util/src/util/Intents.ts +++ b/util/src/util/Intents.ts @@ -2,20 +2,31 @@ import { BitField } from "./BitField"; export class Intents extends BitField { static FLAGS = { - GUILDS: BigInt(1) << BigInt(0), - GUILD_MEMBERS: BigInt(1) << BigInt(1), - GUILD_BANS: BigInt(1) << BigInt(2), - GUILD_EMOJIS: BigInt(1) << BigInt(3), - GUILD_INTEGRATIONS: BigInt(1) << BigInt(4), - GUILD_WEBHOOKS: BigInt(1) << BigInt(5), - GUILD_INVITES: BigInt(1) << BigInt(6), - GUILD_VOICE_STATES: BigInt(1) << BigInt(7), - GUILD_PRESENCES: BigInt(1) << BigInt(8), - GUILD_MESSAGES: BigInt(1) << BigInt(9), - GUILD_MESSAGE_REACTIONS: BigInt(1) << BigInt(10), - GUILD_MESSAGE_TYPING: BigInt(1) << BigInt(11), - DIRECT_MESSAGES: BigInt(1) << BigInt(12), - DIRECT_MESSAGE_REACTIONS: BigInt(1) << BigInt(13), - DIRECT_MESSAGE_TYPING: BigInt(1) << BigInt(14), + GUILDS: BigInt(1) << BigInt(0), // guilds and guild merge-split events affecting the user + GUILD_MEMBERS: BigInt(1) << BigInt(1), // memberships + GUILD_BANS: BigInt(1) << BigInt(2), // bans and ban lists + GUILD_EMOJIS: BigInt(1) << BigInt(3), // custom emojis + GUILD_INTEGRATIONS: BigInt(1) << BigInt(4), // applications + GUILD_WEBHOOKS: BigInt(1) << BigInt(5), // webhooks + GUILD_INVITES: BigInt(1) << BigInt(6), // mass invites (no user can receive user specific invites of another user) + GUILD_VOICE_STATES: BigInt(1) << BigInt(7), // voice updates + GUILD_PRESENCES: BigInt(1) << BigInt(8), // presence updates + GUILD_MESSAGES_METADATA: BigInt(1) << BigInt(9), // guild message metadata + GUILD_MESSAGE_REACTIONS: BigInt(1) << BigInt(10), // guild message reactions + GUILD_MESSAGE_TYPING: BigInt(1) << BigInt(11), // guild channel typing notifications + DIRECT_MESSAGES: BigInt(1) << BigInt(12), // DM or orphan channels + DIRECT_MESSAGE_REACTIONS: BigInt(1) << BigInt(13), // DM or orphan channel message reactions + DIRECT_MESSAGE_TYPING: BigInt(1) << BigInt(14), // DM typing notifications + GUILD_MESSAGES_CONTENT: BigInt(1) << BigInt(15), // guild message content + LIVE_MESSAGE_COMPOSITION: BigInt(1) << BigInt(32), // allow composing messages using the gateway + GUILD_ROUTES: BigInt(1) << BigInt(41), // message routes affecting the guild + DIRECT_MESSAGES_THREADS: BigInt(1) << BigInt(42), // direct message threads + JUMBO_EVENTS: BigInt(1) << BigInt(43), // jumbo events (size limits to be defined later) + LOBBIES: BigInt(1) << BigInt(43), // lobbies + INSTANCE_ROUTES: BigInt(1) << BigInt(60), // all message route changes + INSTANCE_GUILD_CHANGES: BigInt(1) << BigInt(61), // all guild create, guild object patch and guild delete events + INSTANCE_POLICY_UPDATES: BigInt(1) << BigInt(62), // all instance policy updates + INSTANCE_USER_UPDATES: BigInt(1) << BigInt(63) // all instance user updates }; } + From fbfbe184f1c49a50a4634c7e8d7fe99b43402b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 16 Apr 2022 00:22:57 +0300 Subject: [PATCH 44/53] Update Identify.ts --- gateway/src/opcodes/Identify.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index eb15c28f4..860000da7 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -29,8 +29,8 @@ const experiments: any = []; import { check } from "./instanceOf"; import { Recipient } from "@fosscord/util"; -// TODO: bot sharding -// TODO: check priviliged intents +// TODO: user sharding +// TODO: check privileged intents, if defined in the config // TODO: check if already identified export async function onIdentify(this: WebSocket, data: Payload) { @@ -87,7 +87,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { user_id: this.user_id, session_id: session_id, // TODO: check if status is only one of: online, dnd, offline, idle - status: identify.presence?.status || "online", //does the session always start as online? + status: identify.presence?.status || "offline", //does the session always start as online? client_info: { //TODO read from identity client: "desktop", @@ -101,7 +101,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { if (!user) return this.close(CLOSECODES.Authentication_failed); - if (!identify.intents) identify.intents = BigInt("0b11111111111111"); + if (!identify.intents) identify.intents = BigInt("0x6ffffffff"); this.intents = new Intents(identify.intents); if (identify.shard) { this.shard_id = identify.shard[0]; @@ -271,7 +271,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { guild_join_requests: [], // TODO what is this? users: users.filter((x) => x).unique(), merged_members: merged_members, - // shard // TODO: only for bots sharding + // shard // TODO: only for user sharding }; // TODO: send real proper data structure From 9cb3b30d4d6bcf90d6d653740c6d67b61612c8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 16 Apr 2022 08:48:01 +0300 Subject: [PATCH 45/53] jumbo and lobbies are indeed different --- util/src/util/Intents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/util/Intents.ts b/util/src/util/Intents.ts index 8b8915a19..688261454 100644 --- a/util/src/util/Intents.ts +++ b/util/src/util/Intents.ts @@ -22,7 +22,7 @@ export class Intents extends BitField { GUILD_ROUTES: BigInt(1) << BigInt(41), // message routes affecting the guild DIRECT_MESSAGES_THREADS: BigInt(1) << BigInt(42), // direct message threads JUMBO_EVENTS: BigInt(1) << BigInt(43), // jumbo events (size limits to be defined later) - LOBBIES: BigInt(1) << BigInt(43), // lobbies + LOBBIES: BigInt(1) << BigInt(44), // lobbies INSTANCE_ROUTES: BigInt(1) << BigInt(60), // all message route changes INSTANCE_GUILD_CHANGES: BigInt(1) << BigInt(61), // all guild create, guild object patch and guild delete events INSTANCE_POLICY_UPDATES: BigInt(1) << BigInt(62), // all instance policy updates From 7278c6620361ef14bb51fc35c9a11be1e75ad53d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sat, 16 Apr 2022 09:03:23 +0300 Subject: [PATCH 46/53] Update Intents.ts --- util/src/util/Intents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/util/Intents.ts b/util/src/util/Intents.ts index 688261454..d9a60e4a8 100644 --- a/util/src/util/Intents.ts +++ b/util/src/util/Intents.ts @@ -24,7 +24,7 @@ export class Intents extends BitField { JUMBO_EVENTS: BigInt(1) << BigInt(43), // jumbo events (size limits to be defined later) LOBBIES: BigInt(1) << BigInt(44), // lobbies INSTANCE_ROUTES: BigInt(1) << BigInt(60), // all message route changes - INSTANCE_GUILD_CHANGES: BigInt(1) << BigInt(61), // all guild create, guild object patch and guild delete events + INSTANCE_GUILD_CHANGES: BigInt(1) << BigInt(61), // all guild create, guild object patch, split, merge and delete events INSTANCE_POLICY_UPDATES: BigInt(1) << BigInt(62), // all instance policy updates INSTANCE_USER_UPDATES: BigInt(1) << BigInt(63) // all instance user updates }; From f27afe0c5695f23a90b2f6b4aed1537ba6b87ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Sun, 17 Apr 2022 21:15:58 +0300 Subject: [PATCH 47/53] reactions rights enforcement --- .../routes/channels/#channel_id/messages/#message_id/ack.ts | 3 ++- .../channels/#channel_id/messages/#message_id/reactions.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts b/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts index 208c1da46..885c5eca7 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts @@ -4,8 +4,9 @@ import { route } from "@fosscord/api"; const router = Router(); -// TODO: check if message exists +// TODO: public read receipts & privacy scoping // TODO: send read state event to all channel members +// TODO: advance-only notification cursor export interface MessageAcknowledgeSchema { manual?: boolean; diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts b/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts index 6b6a66b26..d93cf70f3 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts @@ -101,7 +101,7 @@ router.get("/:emoji", route({ permission: "VIEW_CHANNEL" }), async (req: Request res.json(users); }); -router.put("/:emoji/:user_id", route({ permission: "READ_MESSAGE_HISTORY" }), async (req: Request, res: Response) => { +router.put("/:emoji/:user_id", route({ permission: "READ_MESSAGE_HISTORY", right: "SELF_ADD_REACTIONS" }), async (req: Request, res: Response) => { const { message_id, channel_id, user_id } = req.params; if (user_id !== "@me") throw new HTTPError("Invalid user"); const emoji = getEmoji(req.params.emoji); From b14d5a615469ffb84a2c1fca2352ae826e5561d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Mon, 18 Apr 2022 18:57:27 +0300 Subject: [PATCH 48/53] Google staff email --- util/src/util/Email.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/util/src/util/Email.ts b/util/src/util/Email.ts index b1a7599bf..6885da335 100644 --- a/util/src/util/Email.ts +++ b/util/src/util/Email.ts @@ -13,7 +13,12 @@ export function adjustEmail(email?: string): string | undefined { // TODO: check accounts with uncommon email domains if (domain === "gmail.com" || domain === "googlemail.com") { // replace .dots and +alternatives -> Gmail Dot Trick https://support.google.com/mail/answer/7436150 and https://generator.email/blog/gmail-generator - return user.replace(/[.]|(\+.*)/g, "") + "@gmail.com"; + let v = user.replace(/[.]|(\+.*)/g, "") + "@gmail.com"; + } + + if (domain === "google.com") { + // replace .dots and +alternatives -> Google Staff GMail Dot Trick + let v = user.replace(/[.]|(\+.*)/g, "") + "@google.com"; } return email; From 8a5f6bad2198b42ad4c342659bb0c24152e7ff78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Mon, 18 Apr 2022 19:09:43 +0300 Subject: [PATCH 49/53] Unified ghost instead of separate ghosts --- api/src/routes/channels/#channel_id/messages/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts index 2fd08b04e..fbcce619d 100644 --- a/api/src/routes/channels/#channel_id/messages/index.ts +++ b/api/src/routes/channels/#channel_id/messages/index.ts @@ -119,7 +119,7 @@ router.get("/", async (req: Request, res: Response) => { delete x.user_ids; }); // @ts-ignore - if (!x.author) x.author = { discriminator: "0000", username: "Deleted User", public_flags: "0", avatar: null }; + if (!x.author) x.author = { id: "4", discriminator: "0000", username: "Fosscord Ghost", public_flags: "0", avatar: null }; x.attachments?.forEach((y: any) => { // dynamically set attachment proxy_url in case the endpoint changed const uri = y.proxy_url.startsWith("http") ? y.proxy_url : `https://example.org${y.proxy_url}`; From 53ca3925bf09c6b00d62edc27d93560578a09c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Mon, 18 Apr 2022 21:21:40 +0300 Subject: [PATCH 50/53] get single message && message rights enforcement --- .../#channel_id/messages/#message_id/index.ts | 12 ++++++++++++ .../routes/channels/#channel_id/messages/index.ts | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts index 58dfb1cc1..a27c71e12 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts @@ -51,6 +51,18 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE return res.json(message); }); +router.get("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => { + const { message_id, channel_id } = req.params; + + const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] }); + + const permissions = await getPermission(req.user_id, undefined, channel_id); + + if (message.author_id !== req.user_id) permissions.hasThrow("READ_MESSAGE_HISTORY"); + + return res.json(message); +}); + router.delete("/", route({}), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts index 2fd08b04e..4cfaf2470 100644 --- a/api/src/routes/channels/#channel_id/messages/index.ts +++ b/api/src/routes/channels/#channel_id/messages/index.ts @@ -8,6 +8,7 @@ import { Embed, emitEvent, getPermission, + getRights, Message, MessageCreateEvent, uploadFile, @@ -149,7 +150,7 @@ const messageUpload = multer({ }); // max upload 50 mb // TODO: dynamically change limit of MessageCreateSchema with config -// TODO: check: sum of all characters in an embed structure must not exceed 6000 characters +// TODO: check: sum of all characters in an embed structure must not exceed instance limits // https://discord.com/developers/docs/resources/channel#create-message // TODO: text channel slowdown @@ -167,7 +168,7 @@ router.post( next(); }, - route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES" }), + route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES" }), async (req: Request, res: Response) => { const { channel_id } = req.params; var body = req.body as MessageCreateSchema; From 3061c24780a2dcf46dc4960d50c3636cab6b918f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkin=20Alp=20G=C3=BCney?= Date: Mon, 18 Apr 2022 22:02:32 +0300 Subject: [PATCH 51/53] general rights enforcement stuff --- api/src/util/handlers/route.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/src/util/handlers/route.ts b/api/src/util/handlers/route.ts index 0048c4dd7..3d3bbc373 100644 --- a/api/src/util/handlers/route.ts +++ b/api/src/util/handlers/route.ts @@ -6,6 +6,7 @@ import { FieldErrors, FosscordApiErrors, getPermission, + getRights, PermissionResolvable, Permissions, RightResolvable, @@ -105,6 +106,8 @@ export function route(opts: RouteOptions) { if (opts.right) { const required = new Rights(opts.right); + req.rights = await getRights(req.user_id); + if (!req.rights || !req.rights.has(required)) { throw FosscordApiErrors.MISSING_RIGHTS.withParams(opts.right as string); } From 96b3929fa4c0d2cc6613957e6f1636d0f7644527 Mon Sep 17 00:00:00 2001 From: TheArcaneBrony Date: Tue, 19 Apr 2022 00:57:58 +0200 Subject: [PATCH 52/53] Use 1 thread on platform where fetching thread/core count fails --- api/src/start.ts | 7 ++++++- bundle/scripts/benchmark/connections.js | 7 ++++++- bundle/src/start.ts | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/api/src/start.ts b/api/src/start.ts index 717e1b8f8..ccb4d1082 100644 --- a/api/src/start.ts +++ b/api/src/start.ts @@ -7,7 +7,12 @@ config(); import { FosscordServer } from "./Server"; import cluster from "cluster"; import os from "os"; -const cores = Number(process.env.THREADS) || os.cpus().length; +var cores = 1; +try { + cores = Number(process.env.THREADS) || os.cpus().length; +} catch { + console.log("[API] Failed to get thread count! Using 1...") +} if (cluster.isMaster && process.env.NODE_ENV == "production") { console.log(`Primary ${process.pid} is running`); diff --git a/bundle/scripts/benchmark/connections.js b/bundle/scripts/benchmark/connections.js index 2a4125b49..ffca26283 100644 --- a/bundle/scripts/benchmark/connections.js +++ b/bundle/scripts/benchmark/connections.js @@ -3,8 +3,13 @@ const cluster = require("cluster"); const WebSocket = require("ws"); const endpoint = process.env.GATEWAY || "ws://localhost:3001"; const connections = Number(process.env.CONNECTIONS) || 50; -const threads = Number(process.env.THREADS) || require("os").cpus().length || 1; const token = process.env.TOKEN; +var cores = 1; +try { + cores = Number(process.env.THREADS) || os.cpus().length; +} catch { + console.log("[Bundle] Failed to get thread count! Using 1...") +} if (!token) { console.error("TOKEN env var missing"); diff --git a/bundle/src/start.ts b/bundle/src/start.ts index 7660b296f..de3b58484 100644 --- a/bundle/src/start.ts +++ b/bundle/src/start.ts @@ -9,7 +9,12 @@ config(); import { execSync } from "child_process"; // TODO: add socket event transmission -let cores = Number(process.env.THREADS) || os.cpus().length; +var cores = 1; +try { + cores = Number(process.env.THREADS) || os.cpus().length; +} catch { + console.log("[API] Failed to get thread count! Using 1...") +} if (cluster.isMaster) { function getCommitOrFail() { From 573052f0c5c53143039950910ad219544caa3f67 Mon Sep 17 00:00:00 2001 From: TheArcaneBrony Date: Tue, 19 Apr 2022 01:43:46 +0200 Subject: [PATCH 53/53] Try catch cpu log --- bundle/src/stats.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bundle/src/stats.ts b/bundle/src/stats.ts index 3c5163c31..0234e0b49 100644 --- a/bundle/src/stats.ts +++ b/bundle/src/stats.ts @@ -4,7 +4,13 @@ import { red } from "picocolors"; export function initStats() { console.log(`[Path] running in ${__dirname}`); - console.log(`[CPU] ${osu.cpu.model()} Cores x${osu.cpu.count()}`); + try { + console.log(`[CPU] ${osu.cpu.model()} Cores x${osu.cpu.count()}`); + } + catch { + console.log('[CPU] Failed to get cpu model!') + } + console.log(`[System] ${os.platform()} ${os.arch()}`); console.log(`[Process] running with PID: ${process.pid}`); if (process.getuid && process.getuid() === 0) {