fix full user object being exposed

This commit is contained in:
MathMan05 2025-10-30 17:19:43 -05:00
parent 67d8b03525
commit 7c26fc5919
7 changed files with 62 additions and 185 deletions

View File

@ -110,11 +110,7 @@ router.delete(
where: { id: message_id, channel_id }, where: { id: message_id, channel_id },
}); });
const already_added = message.reactions.find( const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
(x) =>
(x.emoji.id === emoji.id && emoji.id) ||
x.emoji.name === emoji.name,
);
if (!already_added) throw new HTTPError("Reaction not found", 404); if (!already_added) throw new HTTPError("Reaction not found", 404);
message.reactions.remove(already_added); message.reactions.remove(already_added);
@ -158,19 +154,17 @@ router.get(
const message = await Message.findOneOrFail({ const message = await Message.findOneOrFail({
where: { id: message_id, channel_id }, where: { id: message_id, channel_id },
}); });
const reaction = message.reactions.find( const reaction = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
(x) =>
(x.emoji.id === emoji.id && emoji.id) ||
x.emoji.name === emoji.name,
);
if (!reaction) throw new HTTPError("Reaction not found", 404); if (!reaction) throw new HTTPError("Reaction not found", 404);
const users = await User.find({ const users = (
where: { await User.find({
id: In(reaction.user_ids), where: {
}, id: In(reaction.user_ids),
select: PublicUserProjection, },
}); select: PublicUserProjection,
})
).map((user) => user.toPublicUser());
res.json(users); res.json(users);
}, },
@ -201,11 +195,7 @@ router.put(
const message = await Message.findOneOrFail({ const message = await Message.findOneOrFail({
where: { id: message_id, channel_id }, where: { id: message_id, channel_id },
}); });
const already_added = message.reactions.find( const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
(x) =>
(x.emoji.id === emoji.id && emoji.id) ||
x.emoji.name === emoji.name,
);
if (!already_added) req.permission?.hasThrow("ADD_REACTIONS"); if (!already_added) req.permission?.hasThrow("ADD_REACTIONS");
@ -213,15 +203,13 @@ router.put(
const external_emoji = await Emoji.findOneOrFail({ const external_emoji = await Emoji.findOneOrFail({
where: { id: emoji.id }, where: { id: emoji.id },
}); });
if (!already_added && channel.guild_id != external_emoji.guild_id) if (!already_added && channel.guild_id != external_emoji.guild_id) req.permission?.hasThrow("USE_EXTERNAL_EMOJIS");
req.permission?.hasThrow("USE_EXTERNAL_EMOJIS");
emoji.animated = external_emoji.animated; emoji.animated = external_emoji.animated;
emoji.name = external_emoji.name; emoji.name = external_emoji.name;
} }
if (already_added) { if (already_added) {
if (already_added.user_ids.includes(req.user_id)) if (already_added.user_ids.includes(req.user_id)) return res.sendStatus(204); // Do not throw an error ¯\_(ツ)_/¯ as discord also doesn't throw any error
return res.sendStatus(204); // Do not throw an error ¯\_(ツ)_/¯ as discord also doesn't throw any error
already_added.count++; already_added.count++;
already_added.user_ids.push(req.user_id); already_added.user_ids.push(req.user_id);
} else } else
@ -286,30 +274,17 @@ router.delete(
if (user_id === "@me") user_id = req.user_id; if (user_id === "@me") user_id = req.user_id;
else { else {
const permissions = await getPermission( const permissions = await getPermission(req.user_id, undefined, channel_id);
req.user_id,
undefined,
channel_id,
);
permissions.hasThrow("MANAGE_MESSAGES"); permissions.hasThrow("MANAGE_MESSAGES");
} }
const already_added = message.reactions.find( const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
(x) => if (!already_added || !already_added.user_ids.includes(user_id)) throw new HTTPError("Reaction not found", 404);
(x.emoji.id === emoji.id && emoji.id) ||
x.emoji.name === emoji.name,
);
if (!already_added || !already_added.user_ids.includes(user_id))
throw new HTTPError("Reaction not found", 404);
already_added.count--; already_added.count--;
if (already_added.count <= 0) message.reactions.remove(already_added); if (already_added.count <= 0) message.reactions.remove(already_added);
else else already_added.user_ids.splice(already_added.user_ids.indexOf(user_id), 1);
already_added.user_ids.splice(
already_added.user_ids.indexOf(user_id),
1,
);
await message.save(); await message.save();
@ -356,30 +331,17 @@ router.delete(
if (user_id === "@me") user_id = req.user_id; if (user_id === "@me") user_id = req.user_id;
else { else {
const permissions = await getPermission( const permissions = await getPermission(req.user_id, undefined, channel_id);
req.user_id,
undefined,
channel_id,
);
permissions.hasThrow("MANAGE_MESSAGES"); permissions.hasThrow("MANAGE_MESSAGES");
} }
const already_added = message.reactions.find( const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
(x) => if (!already_added || !already_added.user_ids.includes(user_id)) throw new HTTPError("Reaction not found", 404);
(x.emoji.id === emoji.id && emoji.id) ||
x.emoji.name === emoji.name,
);
if (!already_added || !already_added.user_ids.includes(user_id))
throw new HTTPError("Reaction not found", 404);
already_added.count--; already_added.count--;
if (already_added.count <= 0) message.reactions.remove(already_added); if (already_added.count <= 0) message.reactions.remove(already_added);
else else already_added.user_ids.splice(already_added.user_ids.indexOf(user_id), 1);
already_added.user_ids.splice(
already_added.user_ids.indexOf(user_id),
1,
);
await message.save(); await message.save();

View File

@ -17,7 +17,7 @@
*/ */
import { route } from "@spacebar/api"; import { route } from "@spacebar/api";
import { Channel, emitEvent, Member, TypingStartEvent } from "@spacebar/util"; import { Channel, emitEvent, Member, TypingStartEvent, User } from "@spacebar/util";
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
const router: Router = Router({ mergeParams: true }); const router: Router = Router({ mergeParams: true });
@ -43,7 +43,6 @@ router.post(
where: { id: user_id, guild_id: channel.guild_id }, where: { id: user_id, guild_id: channel.guild_id },
relations: ["roles", "user"], relations: ["roles", "user"],
}); });
await emitEvent({ await emitEvent({
event: "TYPING_START", event: "TYPING_START",
channel_id: channel_id, channel_id: channel_id,
@ -51,7 +50,7 @@ router.post(
...(member ...(member
? { ? {
member: { member: {
...member, ...member.toPublicMember(),
roles: member?.roles?.map((x) => x.id), roles: member?.roles?.map((x) => x.id),
}, },
} }

View File

@ -17,18 +17,10 @@
*/ */
import { getIpAdress, route } from "@spacebar/api"; import { getIpAdress, route } from "@spacebar/api";
import { import { Ban, DiscordApiErrors, GuildBanAddEvent, GuildBanRemoveEvent, Member, User, emitEvent } from "@spacebar/util";
Ban,
DiscordApiErrors,
GuildBanAddEvent,
GuildBanRemoveEvent,
Member,
User,
emitEvent,
} from "@spacebar/util";
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { APIBansArray, BanRegistrySchema, GuildBansResponse } from "@spacebar/schemas" import { APIBansArray, BanRegistrySchema, GuildBansResponse } from "@spacebar/schemas";
const router: Router = Router({ mergeParams: true }); const router: Router = Router({ mergeParams: true });
@ -87,14 +79,12 @@ router.get(
query: { query: {
query: { query: {
type: "string", type: "string",
description: description: "Query to match username(s) and display name(s) against (1-32 characters)",
"Query to match username(s) and display name(s) against (1-32 characters)",
required: true, required: true,
}, },
limit: { limit: {
type: "number", type: "number",
description: description: "Max number of members to return (1-10, default 10)",
"Max number of members to return (1-10, default 10)",
required: false, required: false,
}, },
}, },
@ -111,14 +101,11 @@ router.get(
const { guild_id } = req.params; const { guild_id } = req.params;
const limit = Number(req.query.limit) || 10; const limit = Number(req.query.limit) || 10;
if (limit > 10 || limit < 1) if (limit > 10 || limit < 1) throw new HTTPError("Limit must be between 1 and 10");
throw new HTTPError("Limit must be between 1 and 10");
const query = String(req.query.query); const query = String(req.query.query);
if (!query || query.trim().length === 0 || query.length > 32) { if (!query || query.trim().length === 0 || query.length > 32) {
throw new HTTPError( throw new HTTPError("The query must be between 1 and 32 characters in length");
"The query must be between 1 and 32 characters in length",
);
} }
let bans = await Ban.createQueryBuilder("ban") let bans = await Ban.createQueryBuilder("ban")
@ -212,17 +199,10 @@ router.put(
const { guild_id } = req.params; const { guild_id } = req.params;
const banned_user_id = req.params.user_id; const banned_user_id = req.params.user_id;
if ( if (req.user_id === banned_user_id && banned_user_id === req.permission?.cache.guild?.owner_id)
req.user_id === banned_user_id && throw new HTTPError("You are the guild owner, hence can't ban yourself", 403);
banned_user_id === req.permission?.cache.guild?.owner_id
)
throw new HTTPError(
"You are the guild owner, hence can't ban yourself",
403,
);
if (req.permission?.cache.guild?.owner_id === banned_user_id) if (req.permission?.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400);
throw new HTTPError("You can't ban the owner", 400);
const existingBan = await Ban.findOne({ const existingBan = await Ban.findOne({
where: { guild_id: guild_id, user_id: banned_user_id }, where: { guild_id: guild_id, user_id: banned_user_id },
@ -247,7 +227,7 @@ router.put(
event: "GUILD_BAN_ADD", event: "GUILD_BAN_ADD",
data: { data: {
guild_id: guild_id, guild_id: guild_id,
user: banned_user, user: banned_user.toPublicUser(),
}, },
guild_id: guild_id, guild_id: guild_id,
} as GuildBanAddEvent), } as GuildBanAddEvent),

View File

@ -17,14 +17,7 @@
*/ */
import { getIpAdress, route } from "@spacebar/api"; import { getIpAdress, route } from "@spacebar/api";
import { import { Ban, DiscordApiErrors, GuildBanAddEvent, Member, User, emitEvent } from "@spacebar/util";
Ban,
DiscordApiErrors,
GuildBanAddEvent,
Member,
User,
emitEvent,
} from "@spacebar/util";
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { Config } from "@spacebar/util"; import { Config } from "@spacebar/util";
@ -54,19 +47,12 @@ router.post(
const userIds: Array<string> = req.body.user_ids; const userIds: Array<string> = req.body.user_ids;
if (!userIds) throw new HTTPError("The user_ids array is missing", 400); if (!userIds) throw new HTTPError("The user_ids array is missing", 400);
if (userIds.length > Config.get().limits.guild.maxBulkBanUsers) if (userIds.length > Config.get().limits.guild.maxBulkBanUsers) throw new HTTPError("The user_ids array must be between 1 and 200 in length", 400);
throw new HTTPError(
"The user_ids array must be between 1 and 200 in length",
400,
);
const banned_users = []; const banned_users = [];
const failed_users = []; const failed_users = [];
for await (const banned_user_id of userIds) { for await (const banned_user_id of userIds) {
if ( if (req.user_id === banned_user_id && banned_user_id === req.permission?.cache.guild?.owner_id) {
req.user_id === banned_user_id &&
banned_user_id === req.permission?.cache.guild?.owner_id
) {
failed_users.push(banned_user_id); failed_users.push(banned_user_id);
continue; continue;
} }
@ -108,7 +94,7 @@ router.post(
event: "GUILD_BAN_ADD", event: "GUILD_BAN_ADD",
data: { data: {
guild_id: guild_id, guild_id: guild_id,
user: banned_user, user: banned_user.toPublicUser(),
}, },
guild_id: guild_id, guild_id: guild_id,
} as GuildBanAddEvent), } as GuildBanAddEvent),
@ -120,8 +106,7 @@ router.post(
} }
} }
if (banned_users.length === 0 && failed_users.length > 0) if (banned_users.length === 0 && failed_users.length > 0) throw DiscordApiErrors.BULK_BAN_FAILED;
throw DiscordApiErrors.BULK_BAN_FAILED;
return res.json({ return res.json({
banned_users: banned_users, banned_users: banned_users,
failed_users: failed_users, failed_users: failed_users,

View File

@ -17,15 +17,7 @@
*/ */
import { route } from "@spacebar/api"; import { route } from "@spacebar/api";
import { import { Config, Guild, GuildDeleteEvent, GuildMemberRemoveEvent, Member, User, emitEvent } from "@spacebar/util";
Config,
Guild,
GuildDeleteEvent,
GuildMemberRemoveEvent,
Member,
User,
emitEvent,
} from "@spacebar/util";
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
@ -79,17 +71,9 @@ router.delete(
}); });
if (!guild) throw new HTTPError("Guild doesn't exist", 404); if (!guild) throw new HTTPError("Guild doesn't exist", 404);
if (guild.owner_id === req.user_id) if (guild.owner_id === req.user_id) throw new HTTPError("You can't leave your own guild", 400);
throw new HTTPError("You can't leave your own guild", 400); if (autoJoin.enabled && autoJoin.guilds.includes(guild_id) && !autoJoin.canLeave) {
if ( throw new HTTPError("You can't leave instance auto join guilds", 400);
autoJoin.enabled &&
autoJoin.guilds.includes(guild_id) &&
!autoJoin.canLeave
) {
throw new HTTPError(
"You can't leave instance auto join guilds",
400,
);
} }
await Promise.all([ await Promise.all([
@ -109,7 +93,7 @@ router.delete(
event: "GUILD_MEMBER_REMOVE", event: "GUILD_MEMBER_REMOVE",
data: { data: {
guild_id: guild_id, guild_id: guild_id,
user: user, user: user.toPublicUser(),
}, },
guild_id: guild_id, guild_id: guild_id,
} as GuildMemberRemoveEvent); } as GuildMemberRemoveEvent);

View File

@ -362,14 +362,16 @@ export async function postHandleMessage(message: Message) {
const hasUrl = !!embed.url; const hasUrl = !!embed.url;
return !hasUrl; return !hasUrl;
}); });
await Promise.all([ const author = data.author?.toPublicUser();
emitEvent({ const event = {
event: "MESSAGE_UPDATE", event: "MESSAGE_UPDATE",
channel_id: message.channel_id, channel_id: message.channel_id,
data, data: {
} as MessageUpdateEvent), ...data,
Message.update({ id: message.id, channel_id: message.channel_id }, { embeds: data.embeds }), author,
]); },
} as MessageUpdateEvent;
await Promise.all([emitEvent(event), Message.update({ id: message.id, channel_id: message.channel_id }, { embeds: data.embeds })]);
return; return;
} }

View File

@ -17,30 +17,10 @@
*/ */
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { import { BeforeInsert, BeforeUpdate, Column, Entity, Index, JoinColumn, JoinTable, ManyToMany, ManyToOne, Not, PrimaryGeneratedColumn, RelationId } from "typeorm";
BeforeInsert,
BeforeUpdate,
Column,
Entity,
Index,
JoinColumn,
JoinTable,
ManyToMany,
ManyToOne,
Not,
PrimaryGeneratedColumn,
RelationId,
} from "typeorm";
import { Ban, Channel, PublicGuildRelations } from "."; import { Ban, Channel, PublicGuildRelations } from ".";
import { ReadyGuildDTO } from "../dtos"; import { ReadyGuildDTO } from "../dtos";
import { import { GuildCreateEvent, GuildDeleteEvent, GuildMemberAddEvent, GuildMemberRemoveEvent, GuildMemberUpdateEvent, MessageCreateEvent } from "../interfaces";
GuildCreateEvent,
GuildDeleteEvent,
GuildMemberAddEvent,
GuildMemberRemoveEvent,
GuildMemberUpdateEvent,
MessageCreateEvent,
} from "../interfaces";
import { Config, emitEvent } from "../util"; import { Config, emitEvent } from "../util";
import { DiscordApiErrors } from "../util/Constants"; import { DiscordApiErrors } from "../util/Constants";
import { BaseClassWithoutId } from "./BaseClass"; import { BaseClassWithoutId } from "./BaseClass";
@ -186,8 +166,7 @@ export class Member extends BaseClassWithoutId {
select: ["owner_id"], select: ["owner_id"],
where: { id: guild_id }, where: { id: guild_id },
}); });
if (guild.owner_id === user_id) if (guild.owner_id === user_id) throw new Error("The owner cannot be removed of the guild");
throw new Error("The owner cannot be removed of the guild");
const member = await Member.findOneOrFail({ const member = await Member.findOneOrFail({
where: { id: user_id, guild_id }, where: { id: user_id, guild_id },
relations: ["user"], relations: ["user"],
@ -210,7 +189,7 @@ export class Member extends BaseClassWithoutId {
} as GuildDeleteEvent), } as GuildDeleteEvent),
emitEvent({ emitEvent({
event: "GUILD_MEMBER_REMOVE", event: "GUILD_MEMBER_REMOVE",
data: { guild_id, user: member.user }, data: { guild_id, user: member.user.toPublicUser() },
guild_id, guild_id,
} as GuildMemberRemoveEvent), } as GuildMemberRemoveEvent),
]); ]);
@ -249,11 +228,7 @@ export class Member extends BaseClassWithoutId {
]); ]);
} }
static async removeRole( static async removeRole(user_id: string, guild_id: string, role_id: string) {
user_id: string,
guild_id: string,
role_id: string,
) {
const [member] = await Promise.all([ const [member] = await Promise.all([
Member.findOneOrFail({ Member.findOneOrFail({
where: { id: user_id, guild_id }, where: { id: user_id, guild_id },
@ -283,11 +258,7 @@ export class Member extends BaseClassWithoutId {
]); ]);
} }
static async changeNickname( static async changeNickname(user_id: string, guild_id: string, nickname: string) {
user_id: string,
guild_id: string,
nickname: string,
) {
const member = await Member.findOneOrFail({ const member = await Member.findOneOrFail({
where: { where: {
id: user_id, id: user_id,
@ -323,10 +294,7 @@ export class Member extends BaseClassWithoutId {
const { maxGuilds } = Config.get().limits.user; const { maxGuilds } = Config.get().limits.user;
const guild_count = await Member.count({ where: { id: user_id } }); const guild_count = await Member.count({ where: { id: user_id } });
if (guild_count >= maxGuilds) { if (guild_count >= maxGuilds) {
throw new HTTPError( throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403);
`You are at the ${maxGuilds} server limit.`,
403,
);
} }
const guild = await Guild.findOneOrFail({ const guild = await Guild.findOneOrFail({
@ -338,10 +306,7 @@ export class Member extends BaseClassWithoutId {
}); });
for await (const channel of guild.channels) { for await (const channel of guild.channels) {
channel.position = await Channel.calculatePosition( channel.position = await Channel.calculatePosition(channel.id, guild_id);
channel.id,
guild_id,
);
} }
const memberCount = await Member.count({ where: { guild_id } }); const memberCount = await Member.count({ where: { guild_id } });
@ -407,7 +372,7 @@ export class Member extends BaseClassWithoutId {
event: "GUILD_MEMBER_ADD", event: "GUILD_MEMBER_ADD",
data: { data: {
...member, ...member,
user, user: user.toPublicUser(),
guild_id, guild_id,
}, },
guild_id, guild_id,