summary refs log tree commit diff
path: root/src/api/routes/users
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/routes/users')
-rw-r--r--src/api/routes/users/#id/delete.ts15
-rw-r--r--src/api/routes/users/#id/index.ts2
-rw-r--r--src/api/routes/users/#id/profile.ts214
-rw-r--r--src/api/routes/users/#id/relationships.ts8
-rw-r--r--src/api/routes/users/@me/channels.ts27
-rw-r--r--src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts11
-rw-r--r--src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts97
-rw-r--r--src/api/routes/users/@me/delete.ts12
-rw-r--r--src/api/routes/users/@me/disable.ts7
-rw-r--r--src/api/routes/users/@me/guilds.ts28
-rw-r--r--src/api/routes/users/@me/guilds/#guild_id/settings.ts11
-rw-r--r--src/api/routes/users/@me/index.ts23
-rw-r--r--src/api/routes/users/@me/mfa/codes-verification.ts18
-rw-r--r--src/api/routes/users/@me/mfa/codes.ts18
-rw-r--r--src/api/routes/users/@me/mfa/totp/disable.ts19
-rw-r--r--src/api/routes/users/@me/mfa/totp/enable.ts20
-rw-r--r--src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts5
-rw-r--r--src/api/routes/users/@me/mfa/webauthn/credentials/index.ts72
-rw-r--r--src/api/routes/users/@me/notes.ts9
-rw-r--r--src/api/routes/users/@me/relationships.ts62
-rw-r--r--src/api/routes/users/@me/settings.ts4
21 files changed, 241 insertions, 441 deletions
diff --git a/src/api/routes/users/#id/delete.ts b/src/api/routes/users/#id/delete.ts

index 5b1a682c..b1888d06 100644 --- a/src/api/routes/users/#id/delete.ts +++ b/src/api/routes/users/#id/delete.ts
@@ -17,13 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - emitEvent, - Member, - PrivateUserProjection, - User, - UserDeleteEvent, -} from "@spacebar/util"; +import { emitEvent, Member, PrivateUserProjection, User, UserDeleteEvent } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router(); @@ -47,10 +41,7 @@ router.post( where: { id: req.params.id }, select: [...PrivateUserProjection, "data"], }); - await Promise.all([ - Member.delete({ id: req.params.id }), - User.delete({ id: req.params.id }), - ]); + await Promise.all([Member.delete({ id: req.params.id }), User.delete({ id: req.params.id })]); // TODO: respect intents as USER_DELETE has potential to cause privacy issues await emitEvent({ @@ -60,7 +51,7 @@ router.post( } as UserDeleteEvent); res.sendStatus(204); - }, + } ); export default router; diff --git a/src/api/routes/users/#id/index.ts b/src/api/routes/users/#id/index.ts
index 1bd413d3..b6fee65e 100644 --- a/src/api/routes/users/#id/index.ts +++ b/src/api/routes/users/#id/index.ts
@@ -35,7 +35,7 @@ router.get( const { id } = req.params; res.json(await User.getPublicUser(id)); - }, + } ); export default router; diff --git a/src/api/routes/users/#id/profile.ts b/src/api/routes/users/#id/profile.ts
index eecec0f3..4a4965d8 100644 --- a/src/api/routes/users/#id/profile.ts +++ b/src/api/routes/users/#id/profile.ts
@@ -30,129 +30,115 @@ import { Request, Response, Router } from "express"; const router: Router = Router(); -router.get( - "/", - route({ responses: { 200: { body: "UserProfileResponse" } } }), - async (req: Request, res: Response) => { - if (req.params.id === "@me") req.params.id = req.user_id; +router.get("/", route({ responses: { 200: { body: "UserProfileResponse" } } }), async (req: Request, res: Response) => { + if (req.params.id === "@me") req.params.id = req.user_id; - const { guild_id, with_mutual_guilds } = req.query; + const { guild_id, with_mutual_guilds } = req.query; - const user = await User.getPublicUser(req.params.id, { - relations: ["connected_accounts"], + const user = await User.getPublicUser(req.params.id, { + relations: ["connected_accounts"], + }); + + const mutual_guilds: object[] = []; + let premium_guild_since; + + if (with_mutual_guilds == "true") { + const requested_member = await Member.find({ + where: { id: req.params.id }, + }); + const self_member = await Member.find({ + where: { id: req.user_id }, }); - const mutual_guilds: object[] = []; - let premium_guild_since; - - if (with_mutual_guilds == "true") { - const requested_member = await Member.find({ - where: { id: req.params.id }, - }); - const self_member = await Member.find({ - where: { id: req.user_id }, - }); - - for (const rmem of requested_member) { - if (rmem.premium_since) { - if (premium_guild_since) { - if (premium_guild_since > rmem.premium_since) { - premium_guild_since = rmem.premium_since; - } - } else { + for (const rmem of requested_member) { + if (rmem.premium_since) { + if (premium_guild_since) { + if (premium_guild_since > rmem.premium_since) { premium_guild_since = rmem.premium_since; } + } else { + premium_guild_since = rmem.premium_since; } - for (const smem of self_member) { - if (smem.guild_id === rmem.guild_id) { - mutual_guilds.push({ - id: rmem.guild_id, - nick: rmem.nick, - }); - } + } + for (const smem of self_member) { + if (smem.guild_id === rmem.guild_id) { + mutual_guilds.push({ + id: rmem.guild_id, + nick: rmem.nick, + }); } } } - - const guild_member = - guild_id && typeof guild_id == "string" - ? await Member.findOneOrFail({ - where: { id: req.params.id, guild_id: guild_id }, - relations: ["roles"], - }) - : undefined; - - // TODO: make proper DTO's in util? - - const userProfile = { - bio: req.user_bot ? null : user.bio, - accent_color: user.accent_color, - banner: user.banner, - pronouns: user.pronouns, - theme_colors: user.theme_colors, - }; - - const guildMemberProfile = { - accent_color: null, - banner: guild_member?.banner || null, - bio: guild_member?.bio || "", - guild_id, - }; - res.json({ - connected_accounts: user.connected_accounts.filter( - (x) => x.visibility != 0, - ), - premium_guild_since: premium_guild_since, // TODO - premium_since: user.premium_since, // TODO - mutual_guilds: mutual_guilds, // TODO {id: "", nick: null} when ?with_mutual_guilds=true - user: user.toPublicUser(), - premium_type: user.premium_type, - profile_themes_experiment_bucket: 4, // TODO: This doesn't make it available, for some reason? - user_profile: userProfile, - guild_member: guild_member?.toPublicMember(), - guild_member_profile: guild_id && guildMemberProfile, - }); - }, -); - -router.patch( - "/", - route({ requestBody: "UserProfileModifySchema" }), - async (req: Request, res: Response) => { - const body = req.body as UserProfileModifySchema; - - if (body.banner) - body.banner = await handleFile( - `/banners/${req.user_id}`, - body.banner as string, - ); - const user = await User.findOneOrFail({ - where: { id: req.user_id }, - select: [...PrivateUserProjection, "data"], - }); - - user.assign(body); - await user.save(); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - delete user.data; - - // TODO: send update member list event in gateway - await emitEvent({ - event: "USER_UPDATE", - user_id: req.user_id, - data: user, - } as UserUpdateEvent); - - res.json({ - accent_color: user.accent_color, - bio: user.bio, - banner: user.banner, - theme_colors: user.theme_colors, - pronouns: user.pronouns, - }); - }, -); + } + + const guild_member = + guild_id && typeof guild_id == "string" + ? await Member.findOneOrFail({ + where: { id: req.params.id, guild_id: guild_id }, + relations: ["roles"], + }) + : undefined; + + // TODO: make proper DTO's in util? + + const userProfile = { + bio: req.user_bot ? null : user.bio, + accent_color: user.accent_color, + banner: user.banner, + pronouns: user.pronouns, + theme_colors: user.theme_colors, + }; + + const guildMemberProfile = { + accent_color: null, + banner: guild_member?.banner || null, + bio: guild_member?.bio || "", + guild_id, + }; + res.json({ + connected_accounts: user.connected_accounts.filter((x) => x.visibility != 0), + premium_guild_since: premium_guild_since, // TODO + premium_since: user.premium_since, // TODO + mutual_guilds: mutual_guilds, // TODO {id: "", nick: null} when ?with_mutual_guilds=true + user: user.toPublicUser(), + premium_type: user.premium_type, + profile_themes_experiment_bucket: 4, // TODO: This doesn't make it available, for some reason? + user_profile: userProfile, + guild_member: guild_member?.toPublicMember(), + guild_member_profile: guild_id && guildMemberProfile, + }); +}); + +router.patch("/", route({ requestBody: "UserProfileModifySchema" }), async (req: Request, res: Response) => { + const body = req.body as UserProfileModifySchema; + + if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string); + const user = await User.findOneOrFail({ + where: { id: req.user_id }, + select: [...PrivateUserProjection, "data"], + }); + + user.assign(body); + await user.save(); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + delete user.data; + + // TODO: send update member list event in gateway + await emitEvent({ + event: "USER_UPDATE", + user_id: req.user_id, + data: user, + } as UserUpdateEvent); + + res.json({ + accent_color: user.accent_color, + bio: user.bio, + banner: user.banner, + theme_colors: user.theme_colors, + pronouns: user.pronouns, + }); +}); export default router; diff --git a/src/api/routes/users/#id/relationships.ts b/src/api/routes/users/#id/relationships.ts
index 3737ca00..c4c128a8 100644 --- a/src/api/routes/users/#id/relationships.ts +++ b/src/api/routes/users/#id/relationships.ts
@@ -46,11 +46,7 @@ router.get( for (const rmem of requested_relations.relationships) { for (const smem of self_relations.relationships) - if ( - rmem.to_id === smem.to_id && - rmem.type === 1 && - rmem.to_id !== req.user_id - ) { + if (rmem.to_id === smem.to_id && rmem.type === 1 && rmem.to_id !== req.user_id) { const relation_user = await User.getPublicUser(rmem.to_id); mutual_relations.push({ @@ -64,7 +60,7 @@ router.get( } res.json(mutual_relations); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/channels.ts b/src/api/routes/users/@me/channels.ts
index 8a8fadd9..ee7fefa7 100644 --- a/src/api/routes/users/@me/channels.ts +++ b/src/api/routes/users/@me/channels.ts
@@ -17,12 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - Channel, - DmChannelCreateSchema, - DmChannelDTO, - Recipient, -} from "@spacebar/util"; +import { Channel, DmChannelCreateSchema, DmChannelDTO, Recipient } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router: Router = Router(); @@ -41,14 +36,8 @@ 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])))); + } ); router.post( @@ -63,14 +52,8 @@ 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)); + } ); export default router; diff --git a/src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts b/src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts
index 789a7878..97c03efd 100644 --- a/src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts +++ b/src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts
@@ -77,18 +77,13 @@ router.get("/", route({}), async (req: Request, res: Response) => { }); if (!connectedAccount) throw DiscordApiErrors.UNKNOWN_CONNECTION; if (connectedAccount.revoked) throw DiscordApiErrors.CONNECTION_REVOKED; - if (!connectedAccount.token_data) - throw new ApiError("No token data", 0, 400); + if (!connectedAccount.token_data) throw new ApiError("No token data", 0, 400); let access_token = connectedAccount.token_data.access_token; const { expires_at, expires_in, fetched_at } = connectedAccount.token_data; - if ( - (expires_at && expires_at < Date.now()) || - (expires_in && fetched_at + expires_in * 1000 < Date.now()) - ) { - if (!(connection instanceof RefreshableConnection)) - throw new ApiError("Access token expired", 0, 400); + if ((expires_at && expires_at < Date.now()) || (expires_in && fetched_at + expires_in * 1000 < Date.now())) { + if (!(connection instanceof RefreshableConnection)) throw new ApiError("Access token expired", 0, 400); const tokenData = await connection.refresh(connectedAccount); access_token = tokenData.access_token; } diff --git a/src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts b/src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts
index 351ec99a..afb5b2e9 100644 --- a/src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts +++ b/src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts
@@ -17,68 +17,59 @@ */ import { route } from "@spacebar/api"; -import { - ConnectedAccount, - ConnectionUpdateSchema, - DiscordApiErrors, - emitEvent, -} from "@spacebar/util"; +import { ConnectedAccount, ConnectionUpdateSchema, DiscordApiErrors, emitEvent } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router(); // TODO: connection update schema -router.patch( - "/", - route({ requestBody: "ConnectionUpdateSchema" }), - async (req: Request, res: Response) => { - const { connection_name, connection_id } = req.params; - const body = req.body as ConnectionUpdateSchema; +router.patch("/", route({ requestBody: "ConnectionUpdateSchema" }), async (req: Request, res: Response) => { + const { connection_name, connection_id } = req.params; + const body = req.body as ConnectionUpdateSchema; - const connection = await ConnectedAccount.findOne({ - where: { - user_id: req.user_id, - external_id: connection_id, - type: connection_name, - }, - select: [ - "external_id", - "type", - "name", - "verified", - "visibility", - "show_activity", - "revoked", - "friend_sync", - "integrations", - ], - }); + const connection = await ConnectedAccount.findOne({ + where: { + user_id: req.user_id, + external_id: connection_id, + type: connection_name, + }, + select: [ + "external_id", + "type", + "name", + "verified", + "visibility", + "show_activity", + "revoked", + "friend_sync", + "integrations", + ], + }); - if (!connection) return DiscordApiErrors.UNKNOWN_CONNECTION; - // TODO: do we need to do anything if the connection is revoked? + if (!connection) return DiscordApiErrors.UNKNOWN_CONNECTION; + // TODO: do we need to do anything if the connection is revoked? - if (typeof body.visibility === "boolean") - //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? - body.visibility = body.visibility ? 1 : 0; - if (typeof body.show_activity === "boolean") - //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? - body.show_activity = body.show_activity ? 1 : 0; - if (typeof body.metadata_visibility === "boolean") - //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? - body.metadata_visibility = body.metadata_visibility ? 1 : 0; + if (typeof body.visibility === "boolean") + //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? + body.visibility = body.visibility ? 1 : 0; + if (typeof body.show_activity === "boolean") + //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? + body.show_activity = body.show_activity ? 1 : 0; + if (typeof body.metadata_visibility === "boolean") + //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? + body.metadata_visibility = body.metadata_visibility ? 1 : 0; - connection.assign(req.body); + connection.assign(req.body); - await ConnectedAccount.update( - { - user_id: req.user_id, - external_id: connection_id, - type: connection_name, - }, - connection, - ); - res.json(connection.toJSON()); - }, -); + await ConnectedAccount.update( + { + user_id: req.user_id, + external_id: connection_id, + type: connection_name, + }, + connection + ); + res.json(connection.toJSON()); +}); router.delete("/", route({}), async (req: Request, res: Response) => { const { connection_name, connection_id } = req.params; diff --git a/src/api/routes/users/@me/delete.ts b/src/api/routes/users/@me/delete.ts
index e36a1e92..a8e043f6 100644 --- a/src/api/routes/users/@me/delete.ts +++ b/src/api/routes/users/@me/delete.ts
@@ -46,10 +46,7 @@ router.post( if (user.data.hash) { // guest accounts can delete accounts without password - correctpass = await bcrypt.compare( - req.body.password, - user.data.hash, - ); + correctpass = await bcrypt.compare(req.body.password, user.data.hash); if (!correctpass) { throw new HTTPError(req.t("auth:login.INVALID_PASSWORD")); } @@ -58,16 +55,13 @@ router.post( // TODO: decrement guild member count if (correctpass) { - await Promise.all([ - User.delete({ id: req.user_id }), - Member.delete({ id: req.user_id }), - ]); + await Promise.all([User.delete({ id: req.user_id }), Member.delete({ id: req.user_id })]); res.sendStatus(204); } else { res.sendStatus(401); } - }, + } ); export default router; diff --git a/src/api/routes/users/@me/disable.ts b/src/api/routes/users/@me/disable.ts
index b4d03e62..8d9e161c 100644 --- a/src/api/routes/users/@me/disable.ts +++ b/src/api/routes/users/@me/disable.ts
@@ -45,10 +45,7 @@ router.post( if (user.data.hash) { // guest accounts can delete accounts without password - correctpass = await bcrypt.compare( - req.body.password, - user.data.hash, - ); //Not sure if user typed right password :/ + correctpass = await bcrypt.compare(req.body.password, user.data.hash); //Not sure if user typed right password :/ } if (correctpass) { @@ -61,7 +58,7 @@ router.post( code: 50018, }); } - }, + } ); export default router; diff --git a/src/api/routes/users/@me/guilds.ts b/src/api/routes/users/@me/guilds.ts
index 0bce432b..1d2f79ce 100644 --- a/src/api/routes/users/@me/guilds.ts +++ b/src/api/routes/users/@me/guilds.ts
@@ -17,15 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - Config, - Guild, - GuildDeleteEvent, - GuildMemberRemoveEvent, - Member, - User, - emitEvent, -} from "@spacebar/util"; +import { Config, Guild, GuildDeleteEvent, GuildMemberRemoveEvent, Member, User, emitEvent } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; @@ -53,7 +45,7 @@ router.get( } res.json(guild); - }, + } ); // user send to leave a certain guild @@ -79,17 +71,9 @@ router.delete( }); if (!guild) throw new HTTPError("Guild doesn't exist", 404); - if (guild.owner_id === req.user_id) - throw new HTTPError("You can't leave your own guild", 400); - if ( - autoJoin.enabled && - autoJoin.guilds.includes(guild_id) && - !autoJoin.canLeave - ) { - throw new HTTPError( - "You can't leave instance auto join guilds", - 400, - ); + if (guild.owner_id === req.user_id) throw new HTTPError("You can't leave your own guild", 400); + if (autoJoin.enabled && autoJoin.guilds.includes(guild_id) && !autoJoin.canLeave) { + throw new HTTPError("You can't leave instance auto join guilds", 400); } await Promise.all([ @@ -115,7 +99,7 @@ router.delete( } as GuildMemberRemoveEvent); return res.sendStatus(204); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/guilds/#guild_id/settings.ts b/src/api/routes/users/@me/guilds/#guild_id/settings.ts
index ac6586ce..ae5f3922 100644 --- a/src/api/routes/users/@me/guilds/#guild_id/settings.ts +++ b/src/api/routes/users/@me/guilds/#guild_id/settings.ts
@@ -17,12 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - Channel, - Member, - OrmUtils, - UserGuildSettingsSchema, -} from "@spacebar/util"; +import { Channel, Member, OrmUtils, UserGuildSettingsSchema } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router(); @@ -42,7 +37,7 @@ router.get( select: ["settings"], }); return res.json(user.settings); - }, + } ); router.patch( @@ -76,7 +71,7 @@ router.patch( Member.update({ id: req.user_id, guild_id: req.params.guild_id }, user); res.json(user.settings); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index ad11a428..606f33bb 100644 --- a/src/api/routes/users/@me/index.ts +++ b/src/api/routes/users/@me/index.ts
@@ -47,9 +47,9 @@ router.get( await User.findOne({ select: PrivateUserProjection, where: { id: req.user_id }, - }), + }) ); - }, + } ); router.patch( @@ -79,23 +79,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: { @@ -199,7 +188,7 @@ router.patch( ...user, newToken, }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/codes-verification.ts b/src/api/routes/users/@me/mfa/codes-verification.ts
index f71704a9..f7083b53 100644 --- a/src/api/routes/users/@me/mfa/codes-verification.ts +++ b/src/api/routes/users/@me/mfa/codes-verification.ts
@@ -17,13 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - CodesVerificationSchema, - DiscordApiErrors, - User, - generateMfaBackupCodes, -} from "@spacebar/util"; +import { BackupCode, CodesVerificationSchema, DiscordApiErrors, User, generateMfaBackupCodes } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router(); @@ -52,15 +46,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())); @@ -78,7 +68,7 @@ router.post( return res.json({ backup_codes: codes.map((x) => ({ ...x, expired: undefined })), }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index f9cfc4c4..d6e5a481 100644 --- a/src/api/routes/users/@me/mfa/codes.ts +++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -17,13 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - FieldErrors, - generateMfaBackupCodes, - MfaCodesSchema, - User, -} from "@spacebar/util"; +import { BackupCode, FieldErrors, generateMfaBackupCodes, MfaCodesSchema, User } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; @@ -36,8 +30,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 +62,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())); @@ -90,7 +80,7 @@ router.post( return res.json({ backup_codes: codes.map((x) => ({ ...x, expired: undefined })), }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index 362152d7..6a0960d8 100644 --- a/src/api/routes/users/@me/mfa/totp/disable.ts +++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -17,12 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - TotpDisableSchema, - User, - generateToken, -} from "@spacebar/util"; +import { BackupCode, TotpDisableSchema, User, generateToken } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { verifyToken } from "node-2fa"; @@ -53,11 +48,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( @@ -65,20 +56,20 @@ router.post( { mfa_enabled: false, totp_secret: "", - }, + } ); await BackupCode.update( { user: { id: req.user_id } }, { expired: true, - }, + } ); return res.json({ token: await generateToken(user.id), }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index 19836e4d..6d66fb95 100644 --- a/src/api/routes/users/@me/mfa/totp/enable.ts +++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -17,12 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - TotpEnableSchema, - User, - generateMfaBackupCodes, - generateToken, -} from "@spacebar/util"; +import { TotpEnableSchema, User, generateMfaBackupCodes, generateToken } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; @@ -61,21 +56,16 @@ 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); 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), @@ -84,7 +74,7 @@ router.post( expired: undefined, })), }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts b/src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts
index 9cf42def..ba5df994 100644 --- a/src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts +++ b/src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts
@@ -41,11 +41,10 @@ router.delete( }); // disable webauthn if there are no keys left - if (keys === 0) - await User.update({ id: req.user_id }, { webauthn_enabled: false }); + if (keys === 0) await User.update({ id: req.user_id }, { webauthn_enabled: false }); res.sendStatus(204); - }, + } ); export default router; 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 f383ffb7..b8e33da7 100644 --- a/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts +++ b/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts
@@ -35,15 +35,11 @@ import { ExpectedAttestationResult } from "fido2-lib"; import { HTTPError } from "lambert-server"; const router = Router(); -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; }; @@ -67,7 +63,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { securityKeys.map((key) => ({ id: key.id, name: key.name, - })), + })) ); }); @@ -94,24 +90,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: { @@ -121,14 +106,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, @@ -151,35 +133,22 @@ 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 regResult = await WebAuthn.fido2.attestationResult( - clientAttestationResponse, - { - ...attestationExpectations, - factor: "second", - }, + const attestationExpectations: ExpectedAttestationResult = JSON.parse( + Buffer.from(clientAttestationResponse.response.clientDataJSON, "base64").toString() ); + 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"); @@ -191,10 +160,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, @@ -203,7 +169,7 @@ router.post( } else { throw DiscordApiErrors.INVALID_AUTHENTICATION_TOKEN; } - }, + } ); export default router; diff --git a/src/api/routes/users/@me/notes.ts b/src/api/routes/users/@me/notes.ts
index 248e61f9..51dcbd7f 100644 --- a/src/api/routes/users/@me/notes.ts +++ b/src/api/routes/users/@me/notes.ts
@@ -49,7 +49,7 @@ router.get( note_user_id: id, user_id: req.user_id, }); - }, + } ); router.put( @@ -79,10 +79,7 @@ router.put( }, }) ) { - Note.update( - { owner: { id: owner.id }, target: { id: target.id } }, - { owner, target, content: note }, - ); + Note.update({ owner: { id: owner.id }, target: { id: target.id } }, { owner, target, content: note }); } else { Note.insert({ id: Snowflake.generate(), @@ -108,7 +105,7 @@ router.put( }); return res.status(204); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts
index bce0a654..9bee19a3 100644 --- a/src/api/routes/users/@me/relationships.ts +++ b/src/api/routes/users/@me/relationships.ts
@@ -33,10 +33,7 @@ import { HTTPError } from "lambert-server"; const router = Router(); -const userProjection: (keyof User)[] = [ - "relationships", - ...PublicUserProjection, -]; +const userProjection: (keyof User)[] = ["relationships", ...PublicUserProjection]; router.get( "/", @@ -68,7 +65,7 @@ router.get( }); return res.json(related_users); - }, + } ); router.put( @@ -94,9 +91,9 @@ router.put( relations: ["relationships", "relationships.to"], select: userProjection, }), - req.body.type ?? RelationshipType.friends, + req.body.type ?? RelationshipType.friends ); - }, + } ); router.post( @@ -121,16 +118,13 @@ 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, }, }), - req.body.type, + req.body.type ); - }, + } ); router.delete( @@ -148,8 +142,7 @@ router.delete( }), async (req: Request, res: Response) => { const { id } = req.params; - if (id === req.user_id) - throw new HTTPError("You can't remove yourself as a friend"); + if (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 }, @@ -163,12 +156,9 @@ router.delete( }); const 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); - 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 @@ -203,20 +193,14 @@ router.delete( ]); return res.sendStatus(204); - }, + } ); 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 }, @@ -225,15 +209,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 { @@ -265,8 +246,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, @@ -282,8 +262,7 @@ async function updateRelationship( }); if (friendRequest) { - if (friendRequest.type === RelationshipType.blocked) - throw new HTTPError("The user blocked you"); + 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 @@ -292,12 +271,9 @@ async function updateRelationship( } if (relationship) { - if (relationship.type === RelationshipType.outgoing) - throw new HTTPError("You already sent a friend request"); + 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", - ); + 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; diff --git a/src/api/routes/users/@me/settings.ts b/src/api/routes/users/@me/settings.ts
index d22d6de1..a6e2f92a 100644 --- a/src/api/routes/users/@me/settings.ts +++ b/src/api/routes/users/@me/settings.ts
@@ -40,7 +40,7 @@ router.get( relations: ["settings"], }); return res.json(user.settings); - }, + } ); router.patch( @@ -73,7 +73,7 @@ router.patch( await user.settings.save(); res.json({ ...user.settings, index: undefined }); - }, + } ); export default router;