From 9d2438167cd9e99bce38f69e9e4e93941fcc32f0 Mon Sep 17 00:00:00 2001 From: cha0s Date: Sun, 13 Dec 2020 12:15:21 -0600 Subject: [PATCH] feat: chat ban enforcement --- packages/chat/src/client/effects.js | 13 +++++++++++-- packages/chat/src/index.js | 4 ++++ packages/chat/src/packets/join.server.js | 14 +++++++++++++- packages/chat/src/packets/message.server.js | 3 +++ packages/chat/src/state.js | 4 +++- packages/user/src/models/user-reddichat.js | 10 ++++++++++ 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/packages/chat/src/client/effects.js b/packages/chat/src/client/effects.js index 19e3e48..a9b68d6 100644 --- a/packages/chat/src/client/effects.js +++ b/packages/chat/src/client/effects.js @@ -1,6 +1,6 @@ import {parseChannel} from '@reddichat/core'; import {createLimiter} from '@latus/governor/client'; -import {push} from 'connected-react-router'; +import {push, replace} from 'connected-react-router'; import {v4 as uuidv4} from 'uuid'; import { @@ -34,7 +34,16 @@ export default ({config: {'%socket': socket}}) => { [submitJoin]: async ({dispatch}, {payload}) => { const {channel} = payload; try { - const {canonical, messages, users} = await socket.send(['Join', payload]); + const { + canonical, + isBanned, + messages, + users, + } = await socket.send(['Join', payload]); + if (isBanned) { + dispatch(replace('/chat')); + return; + } const realChannel = canonical ? parseChannel(canonical) : channel; dispatch(join({ channel: realChannel, diff --git a/packages/chat/src/index.js b/packages/chat/src/index.js index 8589831..0afa907 100644 --- a/packages/chat/src/index.js +++ b/packages/chat/src/index.js @@ -49,6 +49,10 @@ export default { res.redirect(`/chat${chat.name}`); return; } + if (req.user && await req.user.isBannedFrom(chat)) { + res.redirect('/chat'); + return; + } } catch (error) { res.redirect('/chat'); diff --git a/packages/chat/src/packets/join.server.js b/packages/chat/src/packets/join.server.js index 5a692c1..cb5e7c9 100644 --- a/packages/chat/src/packets/join.server.js +++ b/packages/chat/src/packets/join.server.js @@ -14,6 +14,14 @@ export default (latus) => class JoinServer extends Join(latus) { const {User} = ModelMap(latus); const chat = await ensureCanonical(latus, channel); const canonical = parseChannel(chat.name); + if (req.user && await req.user.isBannedFrom(canonical)) { + return { + isBanned: true, + messages: {}, + users: [], + usernames: {}, + }; + } await joinChannel(latus, canonical, socket); const state = await channelState(req, latus, canonical); const usernames = Object.fromEntries(await Promise.all( @@ -22,7 +30,11 @@ export default (latus) => class JoinServer extends Join(latus) { 0 === id ? 'anonymous' : (await User.findByPk(id)).redditUsername, ]), )); - return {...state, usernames, ...(chat.name !== channel.name ? {canonical: chat.name} : {})}; + return { + ...state, + usernames, + ...(chat.name !== channel.name ? {canonical: chat.name} : {}), + }; } }; diff --git a/packages/chat/src/packets/message.server.js b/packages/chat/src/packets/message.server.js index d820a8c..acb96ff 100644 --- a/packages/chat/src/packets/message.server.js +++ b/packages/chat/src/packets/message.server.js @@ -108,6 +108,9 @@ export default (latus) => class MessageServer extends Message(latus) { throw new ValidationError({code: 403, reason: 'not friends'}); } } + if (user && await user.isBannedFrom(channel)) { + throw new ValidationError({code: 403, reason: 'unauthorized'}); + } if (distinction && !user) { throw new ValidationError({code: 403, reason: 'unauthorized'}); } diff --git a/packages/chat/src/state.js b/packages/chat/src/state.js index c69f022..938a2c4 100644 --- a/packages/chat/src/state.js +++ b/packages/chat/src/state.js @@ -78,7 +78,9 @@ export const channelsToHydrate = async (req, latus) => { }), ))), ); - return Array.from((new Set(channels.map(renderChannel))).values()).map(parseChannel); + return Promise.all(Array.from((new Set(channels.map(renderChannel))).values()) + .map(parseChannel) + .filter((channel) => !user.isBannedFrom(channel))); }; export const chatUserIds = async (req, latus) => { diff --git a/packages/user/src/models/user-reddichat.js b/packages/user/src/models/user-reddichat.js index e71c597..b94fd54 100644 --- a/packages/user/src/models/user-reddichat.js +++ b/packages/user/src/models/user-reddichat.js @@ -12,6 +12,12 @@ export default (User, latus) => class UserReddichat extends User { }; } + get bannedFrom() { + return this.getBannedFrom().then((chatRooms) => ( + Promise.all(chatRooms.map(async ({name}) => name)) + )); + } + async blocks() { return (await this.getBlocks()).map(({blocked}) => blocked); } @@ -39,6 +45,10 @@ export default (User, latus) => class UserReddichat extends User { )); } + async isBannedFrom(channel) { + return -1 !== (await this.bannedFrom).indexOf(renderChannel(channel)); + } + async isModOf(channel) { return -1 !== (await this.modOf).indexOf(renderChannel(channel)); }