Enforce stricter validation on polls
This commit is contained in:
parent
41a538c655
commit
9dc82ad444
9 changed files with 231 additions and 11 deletions
|
|
@ -1,5 +1,7 @@
|
|||
var ChannelModule = require("./module");
|
||||
var Poll = require("../poll").Poll;
|
||||
import { ValidationError } from '../errors';
|
||||
import Config from '../config';
|
||||
|
||||
const TYPE_NEW_POLL = {
|
||||
title: "string",
|
||||
|
|
@ -130,16 +132,55 @@ PollModule.prototype.broadcastPoll = function (isNewPoll) {
|
|||
this.channel.broadcastToRoom(event, obscured, this.roomNoViewHidden);
|
||||
};
|
||||
|
||||
PollModule.prototype.handleNewPoll = function (user, data) {
|
||||
PollModule.prototype.validatePollInput = function validatePollInput(title, options) {
|
||||
if (typeof title !== 'string') {
|
||||
throw new ValidationError('Poll title must be a string.');
|
||||
}
|
||||
if (title.length > 255) {
|
||||
throw new ValidationError('Poll title must be no more than 255 characters long.');
|
||||
}
|
||||
if (!Array.isArray(options)) {
|
||||
throw new ValidationError('Poll options must be an array.');
|
||||
}
|
||||
if (options.length > Config.get('poll.max-options')) {
|
||||
throw new ValidationError(`Polls are limited to a maximum of ${Config.get('poll.max-options')} options.`);
|
||||
}
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
if (typeof options[i] !== 'string') {
|
||||
throw new ValidationError('Poll options must be strings.');
|
||||
}
|
||||
if (options[i].length === 0 || options[i].length > 255) {
|
||||
throw new ValidationError('Poll options must be 1-255 characters long.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PollModule.prototype.handleNewPoll = function (user, data, ack) {
|
||||
if (!this.channel.modules.permissions.canControlPoll(user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var title = data.title.substring(0, 255);
|
||||
var opts = data.opts.map(function (x) { return (""+x).substring(0, 255); });
|
||||
var obscured = data.obscured;
|
||||
if (typeof data !== 'object' || data === null) {
|
||||
ack({
|
||||
error: {
|
||||
message: 'Invalid data received for poll creation.'
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var poll = new Poll(user.getName(), title, opts, obscured);
|
||||
try {
|
||||
this.validatePollInput(data.title, data.opts);
|
||||
} catch (error) {
|
||||
ack({
|
||||
error: {
|
||||
message: error.message
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var poll = new Poll(user.getName(), data.title, data.opts, data.obscured);
|
||||
var self = this;
|
||||
if (data.hasOwnProperty("timeout") && !isNaN(data.timeout) && data.timeout > 0) {
|
||||
poll.timer = setTimeout(function () {
|
||||
|
|
@ -155,6 +196,7 @@ PollModule.prototype.handleNewPoll = function (user, data) {
|
|||
this.poll = poll;
|
||||
this.broadcastPoll(true);
|
||||
this.channel.logger.log("[poll] " + user.getName() + " opened poll: '" + poll.title + "'");
|
||||
ack({});
|
||||
};
|
||||
|
||||
PollModule.prototype.handleVote = function (user, data) {
|
||||
|
|
@ -198,6 +240,16 @@ PollModule.prototype.handlePollCmd = function (obscured, user, msg, meta) {
|
|||
|
||||
var args = msg.split(",");
|
||||
var title = args.shift();
|
||||
|
||||
try {
|
||||
this.validatePollInput(title, args);
|
||||
} catch (error) {
|
||||
user.socket.emit('errorMsg', {
|
||||
msg: 'Error creating poll: ' + error.message
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var poll = new Poll(user.getName(), title, args, obscured);
|
||||
this.poll = poll;
|
||||
this.broadcastPoll(true);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,10 @@ var defaults = {
|
|||
"google-drive": {
|
||||
"html5-hack-enabled": false
|
||||
},
|
||||
"twitch-client-id": null
|
||||
"twitch-client-id": null,
|
||||
poll: {
|
||||
"max-options": 50
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,3 +7,4 @@ export const CSRFError = createError('CSRFError');
|
|||
export const HTTPError = createError('HTTPError', {
|
||||
status: HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
});
|
||||
export const ValidationError = createError('ValidationError');
|
||||
|
|
@ -133,14 +133,14 @@ function ipLimitReached(sock) {
|
|||
|
||||
function addTypecheckedFunctions(sock) {
|
||||
sock.typecheckedOn = function (msg, template, cb) {
|
||||
sock.on(msg, function (data) {
|
||||
sock.on(msg, function (data, ack) {
|
||||
typecheck(data, template, function (err, data) {
|
||||
if (err) {
|
||||
sock.emit("errorMsg", {
|
||||
msg: "Unexpected error for message " + msg + ": " + err.message
|
||||
});
|
||||
} else {
|
||||
cb(data);
|
||||
cb(data, ack);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue