diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/api/routes/auth/register.ts | 14 | ||||
-rw-r--r-- | src/api/routes/guilds/#guild_id/members/#member_id/index.ts | 25 | ||||
-rw-r--r-- | src/api/routes/guilds/index.ts | 2 | ||||
-rw-r--r-- | src/api/routes/users/#id/profile.ts | 38 | ||||
-rw-r--r-- | src/gateway/opcodes/LazyRequest.ts | 27 | ||||
-rw-r--r-- | src/util/entities/Member.ts | 10 | ||||
-rw-r--r-- | src/util/schemas/UserProfileResponse.ts | 26 | ||||
-rw-r--r-- | src/util/schemas/responses/TypedResponses.ts | 2 | ||||
-rw-r--r-- | src/util/schemas/responses/UserProfileResponse.ts | 31 |
9 files changed, 103 insertions, 72 deletions
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts index 321b4a65..14dc319a 100644 --- a/src/api/routes/auth/register.ts +++ b/src/api/routes/auth/register.ts @@ -225,6 +225,20 @@ router.post( } if (body.password) { + const min = register.password.minLength + ? register.password.minLength + : 8; + if (body.password.length < min) { + throw FieldErrors({ + password: { + code: "PASSWORD_REQUIREMENTS_MIN_LENGTH", + message: req.t( + "auth:register.PASSWORD_REQUIREMENTS_MIN_LENGTH", + { min: min }, + ), + }, + }); + } // the salt is saved in the password refer to bcrypt docs body.password = await bcrypt.hash(body.password, 12); } else if (register.password.required) { diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts index 5f1f6fa7..cafb922e 100644 --- a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts +++ b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts @@ -27,6 +27,8 @@ import { handleFile, Member, MemberChangeSchema, + PublicMemberProjection, + PublicUserProjection, Role, Sticker, } from "@spacebar/util"; @@ -39,7 +41,7 @@ router.get( route({ responses: { 200: { - body: "Member", + body: "APIPublicMember", }, 403: { body: "APIErrorResponse", @@ -55,9 +57,28 @@ router.get( const member = await Member.findOneOrFail({ where: { id: member_id, guild_id }, + relations: ["roles", "user"], + select: { + index: true, + // only grab public member props + ...Object.fromEntries( + PublicMemberProjection.map((x) => [x, true]), + ), + // and public user props + user: Object.fromEntries( + PublicUserProjection.map((x) => [x, true]), + ), + roles: { + id: true, + }, + }, }); - return res.json(member); + return res.json({ + ...member.toPublicMember(), + user: member.user.toPublicUser(), + roles: member.roles.map((x) => x.id), + }); }, ); diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts index 26173ed5..545beb18 100644 --- a/src/api/routes/guilds/index.ts +++ b/src/api/routes/guilds/index.ts @@ -72,7 +72,7 @@ router.post( await Member.addToGuild(req.user_id, guild.id); - res.status(201).json({ id: guild.id }); + res.status(201).json(guild); }, ); diff --git a/src/api/routes/users/#id/profile.ts b/src/api/routes/users/#id/profile.ts index a94eb546..eecec0f3 100644 --- a/src/api/routes/users/#id/profile.ts +++ b/src/api/routes/users/#id/profile.ts @@ -84,18 +84,6 @@ router.get( // TODO: make proper DTO's in util? - const userDto = { - username: user.username, - discriminator: user.discriminator, - id: user.id, - public_flags: user.public_flags, - avatar: user.avatar, - accent_color: user.accent_color, - banner: user.banner, - bio: req.user_bot ? null : user.bio, - bot: user.bot, - }; - const userProfile = { bio: req.user_bot ? null : user.bio, accent_color: user.accent_color, @@ -104,28 +92,6 @@ router.get( theme_colors: user.theme_colors, }; - const guildMemberDto = guild_member - ? { - avatar: guild_member.avatar, - banner: guild_member.banner, - bio: req.user_bot ? null : guild_member.bio, - communication_disabled_until: - guild_member.communication_disabled_until, - deaf: guild_member.deaf, - flags: user.flags, - is_pending: guild_member.pending, - pending: guild_member.pending, // why is this here twice, discord? - joined_at: guild_member.joined_at, - mute: guild_member.mute, - nick: guild_member.nick, - premium_since: guild_member.premium_since, - roles: guild_member.roles - .map((x) => x.id) - .filter((id) => id != guild_id), - user: userDto, - } - : undefined; - const guildMemberProfile = { accent_color: null, banner: guild_member?.banner || null, @@ -139,11 +105,11 @@ router.get( 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: userDto, + 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_id && guildMemberDto, + guild_member: guild_member?.toPublicMember(), guild_member_profile: guild_id && guildMemberProfile, }); }, diff --git a/src/gateway/opcodes/LazyRequest.ts b/src/gateway/opcodes/LazyRequest.ts index cde91a75..77e1a25a 100644 --- a/src/gateway/opcodes/LazyRequest.ts +++ b/src/gateway/opcodes/LazyRequest.ts @@ -27,6 +27,8 @@ import { User, Presence, partition, + Channel, + Permissions, } from "@spacebar/util"; import { WebSocket, @@ -35,6 +37,7 @@ import { OPCODES, Send, } from "@spacebar/gateway"; +import murmur from "murmurhash-js/murmurhash3_gc"; import { check } from "./instanceOf"; // TODO: only show roles/members that have access to this channel @@ -271,6 +274,28 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) { ranges.map((x) => getMembers(guild_id, x as [number, number])), ); + let list_id = "everyone"; + + const channel = await Channel.findOneOrFail({ + where: { id: channel_id }, + }); + if (channel.permission_overwrites) { + const perms: string[] = []; + + channel.permission_overwrites.forEach((overwrite) => { + const { id, allow, deny } = overwrite; + + if (allow.toBigInt() & Permissions.FLAGS.VIEW_CHANNEL) + perms.push(`allow:${id}`); + else if (deny.toBigInt() & Permissions.FLAGS.VIEW_CHANNEL) + perms.push(`deny:${id}`); + }); + + if (perms.length > 0) { + list_id = murmur(perms.sort().join(",")).toString(); + } + } + // TODO: unsubscribe member_events that are not in op.members ops.forEach((op) => { @@ -299,7 +324,7 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) { member_count - (groups.find((x) => x.id == "offline")?.count ?? 0), member_count, - id: "everyone", + id: list_id, guild_id, groups, }, diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts index 8c208202..8be6eae1 100644 --- a/src/util/entities/Member.ts +++ b/src/util/entities/Member.ts @@ -344,11 +344,7 @@ export class Member extends BaseClassWithoutId { relations: ["user", "roles"], take: 10, }) - ).map((member) => ({ - ...member.toPublicMember(), - user: member.user.toPublicUser(), - roles: member.roles.map((x) => x.id), - })); + ).map((member) => member.toPublicMember()); if ( await Member.count({ @@ -455,6 +451,10 @@ export class Member extends BaseClassWithoutId { PublicMemberProjection.forEach((x) => { member[x] = this[x]; }); + + if (member.roles) member.roles = member.roles.map((x: Role) => x.id); + if (member.user) member.user = member.user.toPublicUser(); + return member as PublicMember; } } diff --git a/src/util/schemas/UserProfileResponse.ts b/src/util/schemas/UserProfileResponse.ts deleted file mode 100644 index 10bbcdbf..00000000 --- a/src/util/schemas/UserProfileResponse.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import { PublicConnectedAccount, PublicUser } from ".."; - -export interface UserProfileResponse { - user: PublicUser; - connected_accounts: PublicConnectedAccount; - premium_guild_since?: Date; - premium_since?: Date; -} diff --git a/src/util/schemas/responses/TypedResponses.ts b/src/util/schemas/responses/TypedResponses.ts index 099efba3..4349b93c 100644 --- a/src/util/schemas/responses/TypedResponses.ts +++ b/src/util/schemas/responses/TypedResponses.ts @@ -11,6 +11,7 @@ import { Member, Message, PrivateUser, + PublicMember, PublicUser, Role, Sticker, @@ -68,6 +69,7 @@ export type APIChannelArray = Channel[]; export type APIEmojiArray = Emoji[]; export type APIMemberArray = Member[]; +export type APIPublicMember = PublicMember; export interface APIGuildWithJoinedAt extends Guild { joined_at: string; diff --git a/src/util/schemas/responses/UserProfileResponse.ts b/src/util/schemas/responses/UserProfileResponse.ts index bd1f46dd..eba7cbcc 100644 --- a/src/util/schemas/responses/UserProfileResponse.ts +++ b/src/util/schemas/responses/UserProfileResponse.ts @@ -1,8 +1,37 @@ -import { PublicConnectedAccount, PublicUser } from "../../entities"; +import { + Member, + PublicConnectedAccount, + PublicMember, + PublicUser, + User, +} from "@spacebar/util"; + +export type MutualGuild = { + id: string; + nick?: string; +}; + +export type PublicMemberProfile = Pick< + Member, + "banner" | "bio" | "guild_id" +> & { + accent_color: null; // TODO +}; + +export type UserProfile = Pick< + User, + "bio" | "accent_color" | "banner" | "pronouns" | "theme_colors" +>; export interface UserProfileResponse { user: PublicUser; connected_accounts: PublicConnectedAccount; premium_guild_since?: Date; premium_since?: Date; + mutual_guilds: MutualGuild[]; + premium_type: number; + profile_themes_experiment_bucket: number; + user_profile: UserProfile; + guild_member?: PublicMember; + guild_member_profile?: PublicMemberProfile; } |