From 9613ffa83481b78fcd12e40cacc596db15996dde Mon Sep 17 00:00:00 2001 From: Rory& Date: Wed, 17 Dec 2025 08:25:23 +0100 Subject: [PATCH] Prettier u4 --- src/api/routes/guilds/#guild_id/emojis.ts | 24 +----- src/api/routes/guilds/#guild_id/index.ts | 70 ++++------------- .../routes/guilds/#guild_id/profile/index.ts | 16 +--- src/api/routes/guilds/#guild_id/prune.ts | 30 ++----- src/api/routes/policies/instance/config.ts | 22 ++---- src/api/routes/policies/stats.ts | 9 +-- src/api/routes/users/@me/channels.ts | 18 +---- src/api/routes/users/@me/connections/index.ts | 13 +--- src/api/routes/users/@me/index.ts | 32 ++------ .../users/@me/mfa/codes-verification.ts | 17 +--- src/api/routes/users/@me/mfa/codes.ts | 17 +--- src/api/routes/users/@me/mfa/totp/disable.ts | 14 +--- src/api/routes/users/@me/mfa/totp/enable.ts | 22 ++---- .../@me/mfa/webauthn/credentials/index.ts | 78 ++++--------------- src/api/routes/users/@me/relationships.ts | 67 ++++------------ src/api/routes/users/@me/settings-proto/1.ts | 72 ++++------------- src/api/routes/users/@me/settings-proto/2.ts | 76 +++++------------- src/gateway/Server.ts | 19 +---- 18 files changed, 130 insertions(+), 486 deletions(-) diff --git a/src/api/routes/guilds/#guild_id/emojis.ts b/src/api/routes/guilds/#guild_id/emojis.ts index b770e5b69..c74f939fc 100644 --- a/src/api/routes/guilds/#guild_id/emojis.ts +++ b/src/api/routes/guilds/#guild_id/emojis.ts @@ -17,19 +17,9 @@ */ import { route } from "@spacebar/api"; -import { - Config, - DiscordApiErrors, - Emoji, - GuildEmojisUpdateEvent, - Member, - Snowflake, - User, - emitEvent, - handleFile, -} from "@spacebar/util"; +import { Config, DiscordApiErrors, Emoji, GuildEmojisUpdateEvent, Member, Snowflake, User, emitEvent, handleFile } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { EmojiCreateSchema, EmojiModifySchema } from "@spacebar/schemas" +import { EmojiCreateSchema, EmojiModifySchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -115,10 +105,7 @@ router.post( }); const { maxEmojis } = Config.get().limits.guild; - if (emoji_count >= maxEmojis) - throw DiscordApiErrors.MAXIMUM_NUMBER_OF_EMOJIS_REACHED.withParams( - maxEmojis, - ); + if (emoji_count >= maxEmojis) throw DiscordApiErrors.MAXIMUM_NUMBER_OF_EMOJIS_REACHED.withParams(maxEmojis); if (body.require_colons == null) body.require_colons = true; const user = await User.findOneOrFail({ where: { id: req.user_id } }); @@ -132,10 +119,7 @@ router.post( require_colons: body.require_colons ?? undefined, // schema allows nulls, db does not user: user, managed: false, - animated: - mimeType == "image/gif" || - mimeType == "image/apng" || - mimeType == "video/webm", + animated: mimeType == "image/gif" || mimeType == "image/apng" || mimeType == "video/webm", available: true, roles: [], }).save(); diff --git a/src/api/routes/guilds/#guild_id/index.ts b/src/api/routes/guilds/#guild_id/index.ts index 768e9ce61..d6593bd8e 100644 --- a/src/api/routes/guilds/#guild_id/index.ts +++ b/src/api/routes/guilds/#guild_id/index.ts @@ -17,22 +17,10 @@ */ import { route } from "@spacebar/api"; -import { - Channel, - DiscordApiErrors, - Guild, - GuildUpdateEvent, - Member, - Permissions, - SpacebarApiErrors, - emitEvent, - getPermission, - getRights, - handleFile, -} from "@spacebar/util"; +import { Channel, DiscordApiErrors, Guild, GuildUpdateEvent, Member, Permissions, SpacebarApiErrors, emitEvent, getPermission, getRights, handleFile } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; -import { GuildUpdateSchema } from "@spacebar/schemas" +import { GuildUpdateSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -54,15 +42,8 @@ router.get( async (req: Request, res: Response) => { const { guild_id } = req.params; - const [guild, member] = await Promise.all([ - Guild.findOneOrFail({ where: { id: guild_id } }), - Member.findOne({ where: { guild_id: guild_id, id: req.user_id } }), - ]); - if (!member) - throw new HTTPError( - "You are not a member of the guild you are trying to access", - 401, - ); + const [guild, member] = await Promise.all([Guild.findOneOrFail({ where: { id: guild_id } }), Member.findOne({ where: { guild_id: guild_id, id: req.user_id } })]); + if (!member) throw new HTTPError("You are not a member of the guild you are trying to access", 401); return res.send({ ...guild, @@ -98,10 +79,7 @@ router.patch( 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.withParams( - "MANAGE_GUILDS", - ); + if (!rights.has("MANAGE_GUILDS") && !permission.has("MANAGE_GUILD")) throw DiscordApiErrors.MISSING_PERMISSIONS.withParams("MANAGE_GUILDS"); const guild = await Guild.findOneOrFail({ where: { id: guild_id }, @@ -118,47 +96,25 @@ router.patch( // TODO: guild update check image - if (body.icon && body.icon != guild.icon) - body.icon = await handleFile(`/icons/${guild_id}`, body.icon); + if (body.icon && body.icon != guild.icon) body.icon = await handleFile(`/icons/${guild_id}`, body.icon); - if (body.banner && body.banner !== guild.banner) - body.banner = await handleFile(`/banners/${guild_id}`, body.banner); + if (body.banner && body.banner !== guild.banner) body.banner = await handleFile(`/banners/${guild_id}`, body.banner); - if (body.splash && body.splash !== guild.splash) - body.splash = await handleFile( - `/splashes/${guild_id}`, - body.splash, - ); + if (body.splash && body.splash !== guild.splash) body.splash = await handleFile(`/splashes/${guild_id}`, body.splash); - if ( - body.discovery_splash && - body.discovery_splash !== guild.discovery_splash - ) - body.discovery_splash = await handleFile( - `/discovery-splashes/${guild_id}`, - body.discovery_splash, - ); + if (body.discovery_splash && body.discovery_splash !== guild.discovery_splash) + body.discovery_splash = await handleFile(`/discovery-splashes/${guild_id}`, body.discovery_splash); if (body.features) { - const diff = guild.features - .filter((x) => !body.features?.includes(x)) - .concat( - body.features.filter((x) => !guild.features.includes(x)), - ); + const diff = guild.features.filter((x) => !body.features?.includes(x)).concat(body.features.filter((x) => !guild.features.includes(x))); // TODO move these - const MUTABLE_FEATURES = [ - "COMMUNITY", - "INVITES_DISABLED", - "DISCOVERABLE", - ]; + const MUTABLE_FEATURES = ["COMMUNITY", "INVITES_DISABLED", "DISCOVERABLE"]; for (const feature of diff) { if (MUTABLE_FEATURES.includes(feature)) continue; - throw SpacebarApiErrors.FEATURE_IS_IMMUTABLE.withParams( - feature, - ); + throw SpacebarApiErrors.FEATURE_IS_IMMUTABLE.withParams(feature); } // for some reason, they don't update in the assign. diff --git a/src/api/routes/guilds/#guild_id/profile/index.ts b/src/api/routes/guilds/#guild_id/profile/index.ts index 66e223d8e..8f0e38574 100644 --- a/src/api/routes/guilds/#guild_id/profile/index.ts +++ b/src/api/routes/guilds/#guild_id/profile/index.ts @@ -17,15 +17,9 @@ */ import { route } from "@spacebar/api"; -import { - emitEvent, - GuildMemberUpdateEvent, - handleFile, - Member, - OrmUtils, -} from "@spacebar/util"; +import { emitEvent, GuildMemberUpdateEvent, handleFile, Member, OrmUtils } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { MemberChangeProfileSchema } from "@spacebar/schemas" +import { MemberChangeProfileSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -56,11 +50,7 @@ router.patch( relations: ["roles", "user"], }); - if (body.banner) - body.banner = await handleFile( - `/guilds/${guild_id}/users/${req.user_id}/avatars`, - body.banner as string, - ); + if (body.banner) body.banner = await handleFile(`/guilds/${guild_id}/users/${req.user_id}/avatars`, body.banner as string); member = await OrmUtils.mergeDeep(member, body); diff --git a/src/api/routes/guilds/#guild_id/prune.ts b/src/api/routes/guilds/#guild_id/prune.ts index 9d9de6d38..47984e025 100644 --- a/src/api/routes/guilds/#guild_id/prune.ts +++ b/src/api/routes/guilds/#guild_id/prune.ts @@ -23,12 +23,7 @@ import { IsNull, LessThan } from "typeorm"; const router = Router({ mergeParams: true }); //Returns all inactive members, respecting role hierarchy -const inactiveMembers = async ( - guild_id: string, - user_id: string, - days: number, - roles: string[] = [], -) => { +const inactiveMembers = async (guild_id: string, user_id: string, days: number, roles: string[] = []) => { const date = new Date(); date.setDate(date.getDate() - days); //Snowflake should have `generateFromTime` method? Or similar? @@ -54,10 +49,7 @@ const inactiveMembers = async ( if (!members.length) return []; //I'm sure I can do this in the above db query ( and it would probably be better to do so ), but oh well. - if (roles.length && members.length) - members = members.filter((user) => - user.roles?.some((role) => roles.includes(role.id)), - ); + if (roles.length && members.length) members = members.filter((user) => user.roles?.some((role) => roles.includes(role.id))); const me = await Member.findOneOrFail({ where: { id: user_id, guild_id }, @@ -95,12 +87,7 @@ router.get( let roles = req.query.include_roles; if (typeof roles === "string") roles = [roles]; //express will return array otherwise - const members = await inactiveMembers( - req.params.guild_id, - req.user_id, - days, - roles as string[], - ); + const members = await inactiveMembers(req.params.guild_id, req.user_id, days, roles as string[]); res.send({ pruned: members.length }); }, @@ -127,16 +114,9 @@ router.post( if (typeof roles === "string") roles = [roles]; const { guild_id } = req.params; - const members = await inactiveMembers( - guild_id, - req.user_id, - days, - roles as string[], - ); + const members = await inactiveMembers(guild_id, req.user_id, days, roles as string[]); - await Promise.all( - members.map((x) => Member.removeFromGuild(x.id, guild_id)), - ); + await Promise.all(members.map((x) => Member.removeFromGuild(x.id, guild_id))); res.send({ purged: members.length }); }, diff --git a/src/api/routes/policies/instance/config.ts b/src/api/routes/policies/instance/config.ts index 9df7ef164..97fb5093c 100755 --- a/src/api/routes/policies/instance/config.ts +++ b/src/api/routes/policies/instance/config.ts @@ -43,28 +43,20 @@ router.get( limits_user_maxBio: general.limits.user.maxBio, limits_guild_maxEmojis: general.limits.guild.maxEmojis, limits_guild_maxRoles: general.limits.guild.maxRoles, - limits_message_maxCharacters: - general.limits.message.maxCharacters, - limits_message_maxAttachmentSize: - general.limits.message.maxAttachmentSize, - limits_message_maxEmbedDownloadSize: - general.limits.message.maxEmbedDownloadSize, + limits_message_maxCharacters: general.limits.message.maxCharacters, + limits_message_maxAttachmentSize: general.limits.message.maxAttachmentSize, + limits_message_maxEmbedDownloadSize: general.limits.message.maxEmbedDownloadSize, limits_channel_maxWebhooks: general.limits.channel.maxWebhooks, - register_dateOfBirth_requiredc: - general.register.dateOfBirth.required, + register_dateOfBirth_requiredc: general.register.dateOfBirth.required, register_password_required: general.register.password.required, register_disabled: general.register.disabled, register_requireInvite: general.register.requireInvite, - register_allowNewRegistration: - general.register.allowNewRegistration, - register_allowMultipleAccounts: - general.register.allowMultipleAccounts, + register_allowNewRegistration: general.register.allowNewRegistration, + register_allowMultipleAccounts: general.register.allowMultipleAccounts, guild_autoJoin_canLeave: general.guild.autoJoin.canLeave, guild_autoJoin_guilds_x: general.guild.autoJoin.guilds, register_email_required: general.register.email.required, - can_recover_account: - general.email.provider != null && - general.general.frontPage != null, + can_recover_account: general.email.provider != null && general.general.frontPage != null, }; } res.send(outputtedConfig); diff --git a/src/api/routes/policies/stats.ts b/src/api/routes/policies/stats.ts index 9c17e9974..0828c37c2 100644 --- a/src/api/routes/policies/stats.ts +++ b/src/api/routes/policies/stats.ts @@ -17,14 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - Config, - getRights, - Guild, - Member, - Message, - User, -} from "@spacebar/util"; +import { Config, getRights, Guild, Member, Message, User } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router({ mergeParams: true }); diff --git a/src/api/routes/users/@me/channels.ts b/src/api/routes/users/@me/channels.ts index fa9ffe703..9411e72e6 100644 --- a/src/api/routes/users/@me/channels.ts +++ b/src/api/routes/users/@me/channels.ts @@ -19,7 +19,7 @@ import { route } from "@spacebar/api"; import { Channel, DmChannelDTO, Recipient } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { DmChannelCreateSchema } from "@spacebar/schemas" +import { DmChannelCreateSchema } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); @@ -37,13 +37,7 @@ router.get( where: { user_id: req.user_id, closed: false }, relations: ["channel", "channel.recipients"], }); - res.json( - await Promise.all( - recipients.map((r) => - DmChannelDTO.from(r.channel, [req.user_id]), - ), - ), - ); + res.json(await Promise.all(recipients.map((r) => DmChannelDTO.from(r.channel, [req.user_id])))); }, ); @@ -59,13 +53,7 @@ router.post( }), async (req: Request, res: Response) => { const body = req.body as DmChannelCreateSchema; - res.json( - await Channel.createDMChannel( - body.recipients, - req.user_id, - body.name, - ), - ); + res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name)); }, ); diff --git a/src/api/routes/users/@me/connections/index.ts b/src/api/routes/users/@me/connections/index.ts index e02b912a5..00625eeab 100644 --- a/src/api/routes/users/@me/connections/index.ts +++ b/src/api/routes/users/@me/connections/index.ts @@ -27,18 +27,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { where: { user_id: req.user_id, }, - select: [ - "external_id", - "type", - "name", - "verified", - "visibility", - "show_activity", - "revoked", - "token_data", - "friend_sync", - "integrations", - ], + select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "token_data", "friend_sync", "integrations"], }); res.json(connections.map((x) => new ConnectedAccountDTO(x, true))); diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts index 2fb39713c..aba9f928a 100644 --- a/src/api/routes/users/@me/index.ts +++ b/src/api/routes/users/@me/index.ts @@ -17,15 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - Config, - emitEvent, - FieldErrors, - generateToken, - handleFile, - User, - UserUpdateEvent, -} from "@spacebar/util"; +import { Config, emitEvent, FieldErrors, generateToken, handleFile, User, UserUpdateEvent } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; import { PrivateUserProjection, UserModifySchema } from "@spacebar/schemas"; @@ -78,23 +70,12 @@ router.patch( // Populated on password change let newToken: string | undefined; - if (body.avatar) - body.avatar = await handleFile( - `/avatars/${req.user_id}`, - body.avatar as string, - ); - if (body.banner) - body.banner = await handleFile( - `/banners/${req.user_id}`, - body.banner as string, - ); + if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string); + if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string); if (body.password) { if (user.data?.hash) { - const same_password = await bcrypt.compare( - body.password, - user.data.hash || "", - ); + const same_password = await bcrypt.compare(body.password, user.data.hash || ""); if (!same_password) { throw FieldErrors({ password: { @@ -151,10 +132,7 @@ router.patch( } const { maxUsername } = Config.get().limits.user; - if ( - check_username.length > maxUsername || - check_username.length < 2 - ) { + if (check_username.length > maxUsername || check_username.length < 2) { throw FieldErrors({ username: { code: "BASE_TYPE_BAD_LENGTH", diff --git a/src/api/routes/users/@me/mfa/codes-verification.ts b/src/api/routes/users/@me/mfa/codes-verification.ts index 6dba4bb08..c8995d834 100644 --- a/src/api/routes/users/@me/mfa/codes-verification.ts +++ b/src/api/routes/users/@me/mfa/codes-verification.ts @@ -17,14 +17,9 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - DiscordApiErrors, - User, - generateMfaBackupCodes, -} from "@spacebar/util"; +import { BackupCode, DiscordApiErrors, User, generateMfaBackupCodes } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { CodesVerificationSchema } from "@spacebar/schemas" +import { CodesVerificationSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -52,15 +47,11 @@ router.post( // Once that's done, this route can verify `key` // const user = await User.findOneOrFail({ where: { id: req.user_id } }); - if ((await User.count({ where: { id: req.user_id } })) === 0) - throw DiscordApiErrors.UNKNOWN_USER; + if ((await User.count({ where: { id: req.user_id } })) === 0) throw DiscordApiErrors.UNKNOWN_USER; let codes: BackupCode[]; if (regenerate) { - await BackupCode.update( - { user: { id: req.user_id } }, - { expired: true }, - ); + await BackupCode.update({ user: { id: req.user_id } }, { expired: true }); codes = generateMfaBackupCodes(req.user_id); await Promise.all(codes.map((x) => x.save())); diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts index 389dc01d2..579a106e3 100644 --- a/src/api/routes/users/@me/mfa/codes.ts +++ b/src/api/routes/users/@me/mfa/codes.ts @@ -17,15 +17,10 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - FieldErrors, - generateMfaBackupCodes, - User, -} from "@spacebar/util"; +import { BackupCode, FieldErrors, generateMfaBackupCodes, User } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; -import { MfaCodesSchema } from "@spacebar/schemas" +import { MfaCodesSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -36,8 +31,7 @@ router.post( route({ requestBody: "MfaCodesSchema", deprecated: true, - description: - "This route is replaced with users/@me/mfa/codes-verification in newer clients", + description: "This route is replaced with users/@me/mfa/codes-verification in newer clients", responses: { 200: { body: "APIBackupCodeArray", @@ -69,10 +63,7 @@ router.post( let codes: BackupCode[]; if (regenerate) { - await BackupCode.update( - { user: { id: req.user_id } }, - { expired: true }, - ); + await BackupCode.update({ user: { id: req.user_id } }, { expired: true }); codes = generateMfaBackupCodes(req.user_id); await Promise.all(codes.map((x) => x.save())); diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts index b266fcfe8..003dcb744 100644 --- a/src/api/routes/users/@me/mfa/totp/disable.ts +++ b/src/api/routes/users/@me/mfa/totp/disable.ts @@ -17,15 +17,11 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - User, - generateToken, -} from "@spacebar/util"; +import { BackupCode, User, generateToken } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { verifyToken } from "node-2fa"; -import { TotpDisableSchema } from "@spacebar/schemas" +import { TotpDisableSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -53,11 +49,7 @@ router.post( const backup = await BackupCode.findOne({ where: { code: body.code } }); if (!backup) { const ret = verifyToken(user.totp_secret || "", body.code); - if (!ret || ret.delta != 0) - throw new HTTPError( - req.t("auth:login.INVALID_TOTP_CODE"), - 60008, - ); + if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); } await User.update( diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts index 3d6f4a80d..f0563e30f 100644 --- a/src/api/routes/users/@me/mfa/totp/enable.ts +++ b/src/api/routes/users/@me/mfa/totp/enable.ts @@ -17,16 +17,12 @@ */ import { route } from "@spacebar/api"; -import { - User, - generateMfaBackupCodes, - generateToken, -} from "@spacebar/util"; +import { User, generateMfaBackupCodes, generateToken } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { verifyToken } from "node-2fa"; -import { TotpEnableSchema } from "@spacebar/schemas" +import { TotpEnableSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -61,21 +57,15 @@ router.post( } } - if (!body.secret) - throw new HTTPError(req.t("auth:login.INVALID_TOTP_SECRET"), 60005); + if (!body.secret) throw new HTTPError(req.t("auth:login.INVALID_TOTP_SECRET"), 60005); - if (!body.code) - throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); + if (!body.code) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); - if (verifyToken(body.secret, body.code)?.delta != 0) - throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); + if (verifyToken(body.secret, body.code)?.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); const backup_codes = generateMfaBackupCodes(req.user_id); await Promise.all(backup_codes.map((x) => x.save())); - await User.update( - { id: req.user_id }, - { mfa_enabled: true, totp_secret: body.secret }, - ); + await User.update({ id: req.user_id }, { mfa_enabled: true, totp_secret: body.secret }); res.send({ token: await generateToken(user.id), diff --git a/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts b/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts index 1225cd34f..0c4b733db 100644 --- a/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts +++ b/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts @@ -17,31 +17,19 @@ */ import { route } from "@spacebar/api"; -import { - DiscordApiErrors, - FieldErrors, - generateWebAuthnTicket, - SecurityKey, - User, - verifyWebAuthnToken, - WebAuthn, -} from "@spacebar/util"; +import { DiscordApiErrors, FieldErrors, generateWebAuthnTicket, SecurityKey, User, verifyWebAuthnToken, WebAuthn } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; import { ExpectedAttestationResult } from "fido2-lib"; import { HTTPError } from "lambert-server"; -import { CreateWebAuthnCredentialSchema, GenerateWebAuthnCredentialsSchema, WebAuthnPostSchema } from "@spacebar/schemas" +import { CreateWebAuthnCredentialSchema, GenerateWebAuthnCredentialsSchema, WebAuthnPostSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); -const isGenerateSchema = ( - body: WebAuthnPostSchema, -): body is GenerateWebAuthnCredentialsSchema => { +const isGenerateSchema = (body: WebAuthnPostSchema): body is GenerateWebAuthnCredentialsSchema => { return "password" in body; }; -const isCreateSchema = ( - body: WebAuthnPostSchema, -): body is CreateWebAuthnCredentialSchema => { +const isCreateSchema = (body: WebAuthnPostSchema): body is CreateWebAuthnCredentialSchema => { return "credential" in body; }; @@ -92,24 +80,13 @@ router.post( where: { id: req.user_id, }, - select: [ - "data", - "id", - "disabled", - "deleted", - "totp_secret", - "mfa_enabled", - "username", - ], + select: ["data", "id", "disabled", "deleted", "totp_secret", "mfa_enabled", "username"], relations: ["settings"], }); if (isGenerateSchema(req.body)) { const { password } = req.body; - const same_password = await bcrypt.compare( - password, - user.data.hash || "", - ); + const same_password = await bcrypt.compare(password, user.data.hash || ""); if (!same_password) { throw FieldErrors({ password: { @@ -119,14 +96,11 @@ router.post( }); } - const registrationOptions = - await WebAuthn.fido2.attestationOptions(); + const registrationOptions = await WebAuthn.fido2.attestationOptions(); const challenge = JSON.stringify({ publicKey: { ...registrationOptions, - challenge: Buffer.from( - registrationOptions.challenge, - ).toString("base64"), + challenge: Buffer.from(registrationOptions.challenge).toString("base64"), user: { id: user.id, name: user.username, @@ -149,35 +123,20 @@ router.post( const clientAttestationResponse = JSON.parse(credential); - if (!clientAttestationResponse.rawId) - throw new HTTPError("Missing rawId", 400); + if (!clientAttestationResponse.rawId) throw new HTTPError("Missing rawId", 400); - const rawIdBuffer = Buffer.from( - clientAttestationResponse.rawId, - "base64", - ); + const rawIdBuffer = Buffer.from(clientAttestationResponse.rawId, "base64"); clientAttestationResponse.rawId = toArrayBuffer(rawIdBuffer); - const attestationExpectations: ExpectedAttestationResult = - JSON.parse( - Buffer.from( - clientAttestationResponse.response.clientDataJSON, - "base64", - ).toString(), - ); + const attestationExpectations: ExpectedAttestationResult = JSON.parse(Buffer.from(clientAttestationResponse.response.clientDataJSON, "base64").toString()); - const regResult = await WebAuthn.fido2.attestationResult( - clientAttestationResponse, - { - ...attestationExpectations, - factor: "second", - }, - ); + const regResult = await WebAuthn.fido2.attestationResult(clientAttestationResponse, { + ...attestationExpectations, + factor: "second", + }); const authnrData = regResult.authnrData; - const keyId = Buffer.from(authnrData.get("credId")).toString( - "base64", - ); + const keyId = Buffer.from(authnrData.get("credId")).toString("base64"); const counter = authnrData.get("counter"); const publicKey = authnrData.get("credentialPublicKeyPem"); @@ -189,10 +148,7 @@ router.post( key_id: keyId, }); - await Promise.all([ - securityKey.save(), - User.update({ id: req.user_id }, { webauthn_enabled: true }), - ]); + await Promise.all([securityKey.save(), User.update({ id: req.user_id }, { webauthn_enabled: true })]); return res.json({ name, diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts index a83c24deb..d3df9eb05 100644 --- a/src/api/routes/users/@me/relationships.ts +++ b/src/api/routes/users/@me/relationships.ts @@ -17,25 +17,14 @@ */ import { route } from "@spacebar/api"; -import { - Config, - DiscordApiErrors, - Relationship, - RelationshipAddEvent, - RelationshipRemoveEvent, - User, - emitEvent, -} from "@spacebar/util"; +import { Config, DiscordApiErrors, Relationship, RelationshipAddEvent, RelationshipRemoveEvent, User, emitEvent } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { PublicUserProjection, RelationshipType } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); -const userProjection: (keyof User)[] = [ - "relationships", - ...PublicUserProjection, -]; +const userProjection: (keyof User)[] = ["relationships", ...PublicUserProjection]; router.get( "/", @@ -111,10 +100,7 @@ router.post( relations: ["relationships", "relationships.to"], select: userProjection, where: { - discriminator: String(req.body.discriminator).padStart( - 4, - "0", - ), //Discord send the discriminator as integer, we need to add leading zeroes + discriminator: String(req.body.discriminator).padStart(4, "0"), //Discord send the discriminator as integer, we need to add leading zeroes username: req.body.username, }, }), @@ -138,8 +124,7 @@ router.delete( }), async (req: Request, res: Response) => { const { user_id } = req.params; - if (user_id === req.user_id) - throw new HTTPError("You can't remove yourself as a friend"); + if (user_id === req.user_id) throw new HTTPError("You can't remove yourself as a friend"); const user = await User.findOneOrFail({ where: { id: req.user_id }, @@ -153,12 +138,9 @@ router.delete( }); const relationship = user.relationships.find((x) => x.to_id === user_id); - const friendRequest = friend.relationships.find( - (x) => x.to_id === req.user_id, - ); + const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id); - if (!relationship) - throw new HTTPError("You are not friends with the user", 404); + if (!relationship) throw new HTTPError("You are not friends with the user", 404); if (relationship?.type === RelationshipType.blocked) { // unblock user @@ -198,15 +180,9 @@ router.delete( export default router; -async function updateRelationship( - req: Request, - res: Response, - friend: User, - type: RelationshipType, -) { +async function updateRelationship(req: Request, res: Response, friend: User, type: RelationshipType) { const id = friend.id; - if (id === req.user_id) - throw new HTTPError("You can't add yourself as a friend"); + if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend"); const user = await User.findOneOrFail({ where: { id: req.user_id }, @@ -215,15 +191,12 @@ async function updateRelationship( }); let relationship = user.relationships.find((x) => x.to_id === id); - const friendRequest = friend.relationships.find( - (x) => x.to_id === req.user_id, - ); + const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id); // TODO: you can add infinitely many blocked users (should this be prevented?) if (type === RelationshipType.blocked) { if (relationship) { - if (relationship.type === RelationshipType.blocked) - throw new HTTPError("You already blocked the user"); + if (relationship.type === RelationshipType.blocked) throw new HTTPError("You already blocked the user"); relationship.type = RelationshipType.blocked; await relationship.save(); } else { @@ -255,8 +228,7 @@ async function updateRelationship( } const { maxFriends } = Config.get().limits.user; - if (user.relationships.length >= maxFriends) - throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends); + if (user.relationships.length >= maxFriends) throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends); let incoming_relationship = Relationship.create({ nickname: undefined, @@ -272,24 +244,17 @@ async function updateRelationship( }); if (friendRequest) { - if (friendRequest.type === RelationshipType.blocked) - throw new HTTPError("The user blocked you"); - if (friendRequest.type === RelationshipType.friends) - throw new HTTPError("You are already friends with the user"); + if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you"); + if (friendRequest.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user"); // accept friend request incoming_relationship = friendRequest; incoming_relationship.type = RelationshipType.friends; } if (relationship) { - if (relationship.type === RelationshipType.outgoing) - throw new HTTPError("You already sent a friend request"); - if (relationship.type === RelationshipType.blocked) - throw new HTTPError( - "Unblock the user before sending a friend request", - ); - if (relationship.type === RelationshipType.friends) - throw new HTTPError("You are already friends with the user"); + if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request"); + if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request"); + if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user"); outgoing_relationship = relationship; outgoing_relationship.type = RelationshipType.friends; } diff --git a/src/api/routes/users/@me/settings-proto/1.ts b/src/api/routes/users/@me/settings-proto/1.ts index a0559c26b..6f58b422f 100644 --- a/src/api/routes/users/@me/settings-proto/1.ts +++ b/src/api/routes/users/@me/settings-proto/1.ts @@ -18,14 +18,10 @@ import { route } from "@spacebar/api"; import { Request, Response, Router } from "express"; -import { - emitEvent, - OrmUtils, - UserSettingsProtos, -} from "@spacebar/util"; +import { emitEvent, OrmUtils, UserSettingsProtos } from "@spacebar/util"; import { PreloadedUserSettings } from "discord-protos"; import { JsonValue } from "@protobuf-ts/runtime"; -import { SettingsProtoJsonResponse, SettingsProtoResponse, SettingsProtoUpdateJsonSchema, SettingsProtoUpdateSchema } from "@spacebar/schemas" +import { SettingsProtoJsonResponse, SettingsProtoResponse, SettingsProtoUpdateJsonSchema, SettingsProtoUpdateSchema } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); @@ -41,8 +37,7 @@ router.get( query: { atomic: { type: "boolean", - description: - "Whether to try to apply the settings update atomically (default false)", + description: "Whether to try to apply the settings update atomically (default false)", }, }, }), @@ -50,9 +45,7 @@ router.get( const userSettings = await UserSettingsProtos.getOrDefault(req.user_id); res.json({ - settings: PreloadedUserSettings.toBase64( - userSettings.userSettings!, - ), + settings: PreloadedUserSettings.toBase64(userSettings.userSettings!), } as SettingsProtoResponse); }, ); @@ -68,17 +61,11 @@ router.patch( }, }), async (req: Request, res: Response) => { - const { settings, required_data_version } = - req.body as SettingsProtoUpdateSchema; + const { settings, required_data_version } = req.body as SettingsProtoUpdateSchema; const { atomic } = req.query; const updatedSettings = PreloadedUserSettings.fromBase64(settings); - const resultObj = await patchUserSettings( - req.user_id, - updatedSettings, - required_data_version, - atomic == "true", - ); + const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true"); res.json({ settings: PreloadedUserSettings.toBase64(resultObj.settings), @@ -119,23 +106,16 @@ router.patch( query: { atomic: { type: "boolean", - description: - "Whether to try to apply the settings update atomically (default false)", + description: "Whether to try to apply the settings update atomically (default false)", }, }, }), async (req: Request, res: Response) => { - const { settings, required_data_version } = - req.body as SettingsProtoUpdateJsonSchema; + const { settings, required_data_version } = req.body as SettingsProtoUpdateJsonSchema; const { atomic } = req.query; const updatedSettings = PreloadedUserSettings.fromJson(settings); - const resultObj = await patchUserSettings( - req.user_id, - updatedSettings, - required_data_version, - atomic == "true", - ); + const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true"); res.json({ settings: PreloadedUserSettings.toJson(resultObj.settings), @@ -146,20 +126,11 @@ router.patch( //#endregion -async function patchUserSettings( - userId: string, - updatedSettings: PreloadedUserSettings, - required_data_version: number | undefined, - atomic: boolean = false, -) { +async function patchUserSettings(userId: string, updatedSettings: PreloadedUserSettings, required_data_version: number | undefined, atomic: boolean = false) { const userSettings = await UserSettingsProtos.getOrDefault(userId); let settings = userSettings.userSettings!; - if ( - required_data_version && - settings.versions && - settings.versions.dataVersion > required_data_version - ) { + if (required_data_version && settings.versions && settings.versions.dataVersion > required_data_version) { return { settings: settings, out_of_date: true, @@ -167,24 +138,15 @@ async function patchUserSettings( } if ((process.env.LOG_PROTO_UPDATES || process.env.LOG_PROTO_SETTINGS_UPDATES) && process.env.LOG_PROTO_SETTINGS_UPDATES !== "false") - console.log( - `Updating user settings for user ${userId} with atomic=${atomic}:`, - updatedSettings, - ); + console.log(`Updating user settings for user ${userId} with atomic=${atomic}:`, updatedSettings); if (!atomic) { settings = PreloadedUserSettings.fromJson( - Object.assign( - PreloadedUserSettings.toJson(settings) as object, - PreloadedUserSettings.toJson(updatedSettings) as object, - ) as JsonValue, + Object.assign(PreloadedUserSettings.toJson(settings) as object, PreloadedUserSettings.toJson(updatedSettings) as object) as JsonValue, ); } else { settings = PreloadedUserSettings.fromJson( - OrmUtils.mergeDeep( - PreloadedUserSettings.toJson(settings) as object, - PreloadedUserSettings.toJson(updatedSettings) as object, - ) as JsonValue, + OrmUtils.mergeDeep(PreloadedUserSettings.toJson(settings) as object, PreloadedUserSettings.toJson(updatedSettings) as object) as JsonValue, ); } @@ -202,14 +164,14 @@ async function patchUserSettings( data: { settings: { proto: PreloadedUserSettings.toBase64(settings), - type: 1 + type: 1, }, json_settings: { proto: PreloadedUserSettings.toJson(settings), - type: "user_settings" + type: "user_settings", }, partial: false, // Unsure how this should behave - } + }, }); // This should also send a USER_SETTINGS_UPDATE event, but that isn't sent // when using the USER_SETTINGS_PROTOS capability, so we ignore it for now. diff --git a/src/api/routes/users/@me/settings-proto/2.ts b/src/api/routes/users/@me/settings-proto/2.ts index 8335e2197..b37805fdb 100644 --- a/src/api/routes/users/@me/settings-proto/2.ts +++ b/src/api/routes/users/@me/settings-proto/2.ts @@ -18,14 +18,10 @@ import { route } from "@spacebar/api"; import { Request, Response, Router } from "express"; -import { - emitEvent, - OrmUtils, - UserSettingsProtos, -} from "@spacebar/util"; +import { emitEvent, OrmUtils, UserSettingsProtos } from "@spacebar/util"; import { FrecencyUserSettings } from "discord-protos"; import { JsonValue } from "@protobuf-ts/runtime"; -import { SettingsProtoJsonResponse, SettingsProtoResponse, SettingsProtoUpdateJsonSchema, SettingsProtoUpdateSchema } from "@spacebar/schemas" +import { SettingsProtoJsonResponse, SettingsProtoResponse, SettingsProtoUpdateJsonSchema, SettingsProtoUpdateSchema } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); @@ -41,8 +37,7 @@ router.get( query: { atomic: { type: "boolean", - description: - "Whether to try to apply the settings update atomically (default false)", + description: "Whether to try to apply the settings update atomically (default false)", }, }, }), @@ -50,9 +45,7 @@ router.get( const userSettings = await UserSettingsProtos.getOrDefault(req.user_id); res.json({ - settings: FrecencyUserSettings.toBase64( - userSettings.frecencySettings!, - ), + settings: FrecencyUserSettings.toBase64(userSettings.frecencySettings!), } as SettingsProtoResponse); }, ); @@ -68,17 +61,11 @@ router.patch( }, }), async (req: Request, res: Response) => { - const { settings, required_data_version } = - req.body as SettingsProtoUpdateSchema; + const { settings, required_data_version } = req.body as SettingsProtoUpdateSchema; const { atomic } = req.query; const updatedSettings = FrecencyUserSettings.fromBase64(settings); - const resultObj = await patchUserSettings( - req.user_id, - updatedSettings, - required_data_version, - atomic == "true", - ); + const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true"); res.json({ settings: FrecencyUserSettings.toBase64(resultObj.settings), @@ -102,9 +89,7 @@ router.get( const userSettings = await UserSettingsProtos.getOrDefault(req.user_id); res.json({ - settings: FrecencyUserSettings.toJson( - userSettings.frecencySettings!, - ), + settings: FrecencyUserSettings.toJson(userSettings.frecencySettings!), } as SettingsProtoJsonResponse); }, ); @@ -121,23 +106,16 @@ router.patch( query: { atomic: { type: "boolean", - description: - "Whether to try to apply the settings update atomically (default false)", + description: "Whether to try to apply the settings update atomically (default false)", }, }, }), async (req: Request, res: Response) => { - const { settings, required_data_version } = - req.body as SettingsProtoUpdateJsonSchema; + const { settings, required_data_version } = req.body as SettingsProtoUpdateJsonSchema; const { atomic } = req.query; const updatedSettings = FrecencyUserSettings.fromJson(settings); - const resultObj = await patchUserSettings( - req.user_id, - updatedSettings, - required_data_version, - atomic == "true", - ); + const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true"); res.json({ settings: FrecencyUserSettings.toJson(resultObj.settings), @@ -148,20 +126,11 @@ router.patch( //#endregion -async function patchUserSettings( - userId: string, - updatedSettings: FrecencyUserSettings, - required_data_version: number | undefined, - atomic: boolean = false, -) { +async function patchUserSettings(userId: string, updatedSettings: FrecencyUserSettings, required_data_version: number | undefined, atomic: boolean = false) { const userSettings = await UserSettingsProtos.getOrDefault(userId); let settings = userSettings.frecencySettings!; - if ( - required_data_version && - settings.versions && - settings.versions.dataVersion > required_data_version - ) { + if (required_data_version && settings.versions && settings.versions.dataVersion > required_data_version) { return { settings: settings, out_of_date: true, @@ -169,24 +138,15 @@ async function patchUserSettings( } if ((process.env.LOG_PROTO_UPDATES || process.env.LOG_PROTO_FRECENCY_UPDATES) && process.env.LOG_PROTO_FRECENCY_UPDATES !== "false") - console.log( - `Updating frecency settings for user ${userId} with atomic=${atomic}:`, - updatedSettings, - ); + console.log(`Updating frecency settings for user ${userId} with atomic=${atomic}:`, updatedSettings); if (!atomic) { settings = FrecencyUserSettings.fromJson( - Object.assign( - FrecencyUserSettings.toJson(settings) as object, - FrecencyUserSettings.toJson(updatedSettings) as object, - ) as JsonValue, + Object.assign(FrecencyUserSettings.toJson(settings) as object, FrecencyUserSettings.toJson(updatedSettings) as object) as JsonValue, ); } else { settings = FrecencyUserSettings.fromJson( - OrmUtils.mergeDeep( - FrecencyUserSettings.toJson(settings) as object, - FrecencyUserSettings.toJson(updatedSettings) as object, - ) as JsonValue, + OrmUtils.mergeDeep(FrecencyUserSettings.toJson(settings) as object, FrecencyUserSettings.toJson(updatedSettings) as object) as JsonValue, ); } @@ -204,14 +164,14 @@ async function patchUserSettings( data: { settings: { proto: FrecencyUserSettings.toBase64(settings), - type: 2 + type: 2, }, json_settings: { proto: FrecencyUserSettings.toJson(settings), - type: "frecency_settings" + type: "frecency_settings", }, partial: false, // Unsure how this should behave - } + }, }); // This should also send a USER_SETTINGS_UPDATE event, but that isn't sent // when using the USER_SETTINGS_PROTOS capability, so we ignore it for now. diff --git a/src/gateway/Server.ts b/src/gateway/Server.ts index 2ad3e4136..9baba508e 100644 --- a/src/gateway/Server.ts +++ b/src/gateway/Server.ts @@ -18,12 +18,7 @@ import dotenv from "dotenv"; dotenv.config({ quiet: true }); -import { - closeDatabase, - Config, - initDatabase, - initEvent, -} from "@spacebar/util"; +import { closeDatabase, Config, initDatabase, initEvent } from "@spacebar/util"; import ws from "ws"; import { Connection } from "./events/Connection"; import http from "http"; @@ -36,22 +31,14 @@ export class Server { public server: http.Server; public production: boolean; - constructor({ - port, - server, - production, - }: { - port: number; - server?: http.Server; - production?: boolean; - }) { + constructor({ port, server, production }: { port: number; server?: http.Server; production?: boolean }) { this.port = port; this.production = production || false; if (server) this.server = server; else { this.server = http.createServer(function (req, res) { - if(!req.headers.cookie?.split("; ").find(x => x.startsWith("__sb_sessid="))) { + if (!req.headers.cookie?.split("; ").find((x) => x.startsWith("__sb_sessid="))) { res.setHeader("Set-Cookie", `__sb_sessid=${randomString(32)}; Secure; HttpOnly; SameSite=None; Path=/`); }