Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions server/middlewares/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ module.exports = (req, res, next) => {
res.send(
JSON.stringify({
code: 403,
message: "Unauthorized",
})
message: 'Unauthorized',
}),
);
res.end();
} else if (req && req.user && req.user.id && banned.includes(req.user.id)) {
res.status(403);
res.send(
JSON.stringify({
code: 403,
message: "Unauthorized",
})
message: 'Unauthorized',
}),
);
res.end();
} else {
Expand Down
36 changes: 31 additions & 5 deletions server/models/room.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ const Room = new mongoose.Schema({
type: Date,
default: undefined,
},
hiddenAt: {
type: Date,
default: undefined,
},
twitchChannel: {
type: String,
default: undefined,
Expand All @@ -118,11 +122,19 @@ const Room = new mongoose.Schema({
});

Room.index({
expireAt: 1,
}, {
expireAfterSeconds: 0,
hiddenAt: 1,
});

Room.statics.visibleQuery = function visibleQuery(now = new Date()) {
return {
$or: [
{ hiddenAt: { $exists: false } },
{ hiddenAt: null },
{ hiddenAt: { $gt: now } },
],
};
};

Room.virtual('scrambler').get(function () {
return new Scrambow().setType(Events.find((e) => e.id === this.event).scrambler);
});
Expand All @@ -147,6 +159,10 @@ Room.virtual('latestAttempt').get(function () {
return this.attempts[this.attempts.length - 1];
});

Room.methods.isHidden = function isHidden(now = new Date()) {
return this.hiddenAt && this.hiddenAt <= now;
};

Room.methods.start = function () {
this.started = true;

Expand All @@ -166,15 +182,25 @@ Room.methods.pause = function () {
};

Room.methods.updateStale = function updateStale(stale) {
this.expireAt = null;

if (stale) {
this.expireAt = moment().add(10, 'minutes');
if (!this.hiddenAt) {
this.hiddenAt = moment().add(10, 'minutes').toDate();
}
} else {
this.expireAt = null;
this.hiddenAt = null;
}

return this.save();
};

Room.methods.hide = function hide() {
this.expireAt = null;
this.hiddenAt = new Date();
return this.save();
};

Room.methods.addUser = async function (user, spectating, updateAdmin) {
if (this.inRoom.get(user.id.toString())) {
return false;
Expand Down
72 changes: 62 additions & 10 deletions server/socket/namespaces/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ const joinRoomMask = _.partial(_.pick, _, privateRoomKeys);

const fetchRoom = (id) => Room.findById({ _id: id }).populate('users').populate('admin').populate('owner');

const getRooms = (userId) => Room.find().populate('users').populate('admin').populate('owner')
const getRooms = (userId) => Room.find(Room.visibleQuery()).populate('users').populate('admin').populate('owner')
.then((rooms) => rooms.filter((room) => (
userId ? !room.banned.get(userId.toString()) : true
)).map(roomMask));

const roomTimerObj = {};
const roomHideTimerObj = {};

module.exports = (io, middlewares) => {
const ns = () => io.of('/rooms');
Expand All @@ -51,6 +52,36 @@ module.exports = (io, middlewares) => {
return [...sockets].some((socketId) => socketId !== currentSocketId);
};

function clearRoomHideTimer(roomId) {
clearTimeout(roomHideTimerObj[roomId]);
delete roomHideTimerObj[roomId];
}

function scheduleRoomHide(room) {
if (!room.hiddenAt) {
clearRoomHideTimer(room._id);
return;
}

clearRoomHideTimer(room._id);

const time = new Date(room.hiddenAt).getTime() - Date.now();

roomHideTimerObj[room._id] = setTimeout(async () => {
try {
const r = await fetchRoom(room._id);

if (r && r.isHidden()) {
ns().emit(Protocol.ROOM_DELETED, r._id.toString());
}
} catch (err) {
logger.error(err);
} finally {
clearRoomHideTimer(room._id);
}
}, Math.max(time, 0));
}

async function markNormalRoomsStaleOnStartup() {
const rooms = await Room.find({ type: 'normal' })
.populate('users')
Expand All @@ -64,7 +95,8 @@ module.exports = (io, middlewares) => {
});

room.admin = null;
await room.updateStale(true);
const r = await room.updateStale(true);
scheduleRoomHide(r);
}));

logger.info('Marked normal rooms stale on socket startup', {
Expand Down Expand Up @@ -255,6 +287,7 @@ module.exports = (io, middlewares) => {

broadcast(Protocol.USER_LEFT, socket.user.id);
ns().emit(Protocol.GLOBAL_ROOM_UPDATED, roomMask(room));
scheduleRoomHide(room);

if (room.doneWithScramble()) {
logger.debug('everyone done, sending new scramble');
Expand Down Expand Up @@ -294,6 +327,7 @@ module.exports = (io, middlewares) => {
}

socket.room = r;
clearRoomHideTimer(r._id);
socket.emit(Protocol.JOIN, joinRoomMask(r));
cb(null, joinRoomMask(r));

Expand All @@ -317,6 +351,13 @@ module.exports = (io, middlewares) => {
});
}

if (room.isHidden()) {
return cb({
statusCode: 404,
message: `Could not find room with id ${id}`,
});
}

if (room.private && !password) {
return cb({
statusCode: 403,
Expand Down Expand Up @@ -408,15 +449,24 @@ module.exports = (io, middlewares) => {
});
}

Room.deleteOne({ _id: id }).then((res) => {
if (res.deletedCount > 0) {
socket.room = undefined;
cb(null);
ns().emit(Protocol.ROOM_DELETED, id);
} else if (res.deletedCount > 1) {
logger.error(168, 'big problemo');
try {
const room = await Room.findById(id);

if (!room) {
return cb({
statusCode: 404,
message: `Could not find room with id ${id}`,
});
}
});

await room.hide();
clearRoomHideTimer(room._id);
socket.room = undefined;
cb(null);
ns().emit(Protocol.ROOM_DELETED, id);
} catch (e) {
logger.error(e);
}
});

// Register user for room they are currently in
Expand Down Expand Up @@ -621,6 +671,7 @@ module.exports = (io, middlewares) => {

ns().in(socket.room.accessCode).emit(Protocol.USER_LEFT, userId);
ns().emit(Protocol.GLOBAL_ROOM_UPDATED, roomMask(room));
scheduleRoomHide(room);

if (room.doneWithScramble()) {
logger.debug('everyone done, sending new scramble');
Expand Down Expand Up @@ -654,6 +705,7 @@ module.exports = (io, middlewares) => {

ns().in(room.accessCode).emit(Protocol.UPDATE_ROOM, joinRoomMask(room));
ns().emit(Protocol.GLOBAL_ROOM_UPDATED, roomMask(room));
scheduleRoomHide(room);

if (room.doneWithScramble()) {
logger.debug('everyone done, sending new scramble');
Expand Down