diff --git a/src/server/packet/add-favorite.js b/src/server/packet/add-favorite.js index 78db3d4..879b30c 100644 --- a/src/server/packet/add-favorite.js +++ b/src/server/packet/add-favorite.js @@ -4,11 +4,10 @@ import {allModels} from '~/server/models/registrar'; export default { Packet: AddFavorite, - validator: () => true, - responder: async (packet, socket, fn) => { + validator: async () => true, + responder: async (packet, socket) => { const {req} = socket; await req.user.createFavorite({channel: packet.data}); socket.to(`/user/${req.userId}`, packet); - fn(); }, }; diff --git a/src/server/packet/add-friend.js b/src/server/packet/add-friend.js index 1943d2c..5da784a 100644 --- a/src/server/packet/add-friend.js +++ b/src/server/packet/add-friend.js @@ -1,21 +1,29 @@ +import {validateUsername} from '~/common/channel'; import AddFriend from '~/common/packets/add-friend.packet'; import {allModels} from '~/server/models/registrar'; +import ValidationError from './validation-error'; + export default { Packet: AddFriend, - validator: () => true, - responder: async (packet, socket, fn) => { + limiter: {points: 20, duration: 60}, + validator: async ({data: {nameOrStatus}}) => { + if (!validateUsername(nameOrStatus)) { + throw new ValidationError('Invalid username'); + } + }, + responder: async (packet, socket) => { const {req} = socket; const { Friendship, User, } = allModels(); const adderId = req.user.id; - const user = await User.findOne({where: {redditUsername: packet.data.nameOrStatus}}); - if (!user) { - return; - } + const user = ( + await User.findOne({where: {redditUsername: packet.data.nameOrStatus}}) + || await User.create({redditUsername: packet.data.nameOrStatus}) + ); const addeeId = user.id; let friendship = await Friendship.findOne({where: {adderId: addeeId, addeeId: adderId}}); const friendshipIsActive = !!friendship; @@ -33,6 +41,6 @@ export default { nameOrStatus: friendship.status, })); }); - fn(addeeId); + return addeeId; }, }; diff --git a/src/server/packet/block.js b/src/server/packet/block.js index 048b359..9927d79 100644 --- a/src/server/packet/block.js +++ b/src/server/packet/block.js @@ -9,8 +9,8 @@ import {removeFavoritedUser} from './remove-favorite'; export default { Packet: Block, - validator: () => true, - responder: async (packet, socket, fn) => { + validator: async () => true, + responder: async (packet, socket) => { const {req} = socket; const id = packet.data; const {Friendship, User} = allModels(); @@ -29,6 +29,5 @@ export default { socket.to(`/user/${req.userId}`, packet); socket.to(`/user/${id}`, new RemoveFriend(req.userId)); socket.to(`/user/${req.userId}`, new RemoveFriend(id)); - fn(); }, }; diff --git a/src/server/packet/join.js b/src/server/packet/join.js index 57c2d94..2459278 100644 --- a/src/server/packet/join.js +++ b/src/server/packet/join.js @@ -21,11 +21,11 @@ export const userJoin = async (channel, socket) => { export default { Packet: Join, - validator: () => true, - responder: async (packet, socket, fn) => { + validator: async () => true, + responder: async (packet, socket) => { const {req} = socket; const {channel} = packet.data; await userJoin(channel, socket.socket); - fn(await channelState(req, channel)); + return channelState(req, channel); }, }; diff --git a/src/server/packet/leave.js b/src/server/packet/leave.js index 1de0c93..707298c 100644 --- a/src/server/packet/leave.js +++ b/src/server/packet/leave.js @@ -16,10 +16,9 @@ export const userLeave = async (channel, socket) => { export default { Packet: Leave, - validator: () => true, - responder: async (packet, socket, fn) => { + validator: async () => true, + responder: async (packet, socket) => { const {channel} = packet.data; - await userLeave(channel, socket); - fn(); + return userLeave(channel, socket); }, }; diff --git a/src/server/packet/message.js b/src/server/packet/message.js index af357f6..34befe1 100644 --- a/src/server/packet/message.js +++ b/src/server/packet/message.js @@ -8,7 +8,7 @@ import {allModels} from '~/server/models/registrar'; export default { Packet: Message, limiter: {points: 10, duration: 15}, - validator: () => true, + validator: async () => true, responder: async (packet, socket, fn) => { const {req} = socket; const {pubClient} = req.adapter; @@ -35,15 +35,17 @@ export default { uuid, })) )); - pubClient - .multi() - .set(key, JSON.stringify({ - message, - owner, - socket: socket.id, - timestamp, - })) - .expire(key, '/r/anonymous' === channel ? 60 : 600) - .exec(() => fn([timestamp, uuid])); + return new Promise((resolve, reject) => { + pubClient + .multi() + .set(key, JSON.stringify({ + message, + owner, + socket: socket.id, + timestamp, + })) + .expire(key, '/r/anonymous' === channel ? 60 : 600) + .exec((error) => (error ? reject(error) : resolve([timestamp, uuid]))); + }); }, }; diff --git a/src/server/packet/remove-favorite.js b/src/server/packet/remove-favorite.js index 2b1f5be..c31672e 100644 --- a/src/server/packet/remove-favorite.js +++ b/src/server/packet/remove-favorite.js @@ -18,8 +18,8 @@ export const removeFavoritedUser = async (socket, user, other) => { export default { Packet: RemoveFavorite, - validator: () => true, - responder: async (packet, socket, fn) => { + validator: async () => true, + responder: async (packet, socket) => { const {req} = socket; const {Favorite} = allModels(); const favorites = await req.user.getFavorites(); @@ -30,6 +30,5 @@ export default { }, }); socket.to(`/user/${req.userId}`, packet); - fn(); -}, + }, }; diff --git a/src/server/packet/remove-friend.js b/src/server/packet/remove-friend.js index a93f41e..0818595 100644 --- a/src/server/packet/remove-friend.js +++ b/src/server/packet/remove-friend.js @@ -8,8 +8,8 @@ import {removeFavoritedUser} from './remove-favorite'; export default { Packet: RemoveFriend, - validator: () => true, - responder: async (packet, socket, fn) => { + validator: async () => true, + responder: async (packet, socket) => { const {req} = socket; const id = packet.data; const {Friendship, User} = allModels(); @@ -26,6 +26,5 @@ export default { const user = await User.findByPk(id); removeFavoritedUser(socket, user, req.user); removeFavoritedUser(socket, req.user, user); - fn(); }, }; diff --git a/src/server/packet/unblock.js b/src/server/packet/unblock.js index ec11a76..8cb85db 100644 --- a/src/server/packet/unblock.js +++ b/src/server/packet/unblock.js @@ -4,8 +4,8 @@ import {allModels} from '~/server/models/registrar'; export default { Packet: Unblock, - validator: () => true, - responder: async (packet, socket, fn) => { + validator: async () => true, + responder: async (packet, socket) => { const {req} = socket; const {Block: BlockModel} = allModels(); await BlockModel.destroy({ @@ -15,6 +15,5 @@ export default { }, }); socket.to(`/user/${req.userId}`, packet); - fn(); }, }; diff --git a/src/server/packet/usernames.js b/src/server/packet/usernames.js index 2cca314..1467a19 100644 --- a/src/server/packet/usernames.js +++ b/src/server/packet/usernames.js @@ -4,11 +4,11 @@ import {allModels} from '~/server/models/registrar'; export default { Packet: Usernames, - validator: () => true, - responder: async (packet, socket, fn) => { + validator: async () => true, + responder: async (packet) => { const {User} = allModels(); - fn(await Promise.all(packet.data.map( + return Promise.all(packet.data.map( async (id) => (await User.findByPk(id)).redditUsername, - ))); + )); }, }; diff --git a/src/server/packet/validation-error.js b/src/server/packet/validation-error.js new file mode 100644 index 0000000..1e5d16e --- /dev/null +++ b/src/server/packet/validation-error.js @@ -0,0 +1 @@ +export default class ValidationError extends Error {} diff --git a/src/server/sockets.js b/src/server/sockets.js index 9991ff0..e91c45f 100644 --- a/src/server/sockets.js +++ b/src/server/sockets.js @@ -63,22 +63,24 @@ export function createSocketServer(httpServer) { }); socketServer.on('connect', (socket) => { socket.on('packet', async (packet, fn) => { - const {limiter, responder} = packetHandlers.get(packet.constructor); - if (limiter) { - try { + const {limiter, responder, validator} = packetHandlers.get(packet.constructor); + try { + if (limiter) { await limiter.consume(socket.id); - responder(packet, socket, (...args) => fn(undefined, ...args)); - } - catch (error) { - if (error instanceof Error) { - fn({code: 500}); - throw error; - } - fn({code: 429, ttr: Math.round(error.msBeforeNext / 1000) || 1}); } + await validator(packet, socket); + fn(undefined, await responder(packet, socket)); } - else { - responder(packet, socket, (...args) => fn(undefined, ...args)); + catch (error) { + if (error instanceof Error) { + fn({code: 500}); + throw error; + } + if (error.msBeforeNext) { + fn({code: 429, ttr: Math.round(error.msBeforeNext / 1000) || 1}); + return; + } + fn(error); } }); socket.on('disconnecting', async () => {