Skip to content

Commit

Permalink
Sentry fixes (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
halkeye committed May 8, 2020
1 parent 3907c5a commit 5780557
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 73 deletions.
51 changes: 3 additions & 48 deletions api/helpers/sdtd/fill-custom-variables.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,54 +32,9 @@ module.exports = {


fn: async function (inputs, exits) {

let vars = findVariables(inputs.command);

for (const variableString of vars) {
inputs.command = replaceAllInString(inputs.command, `\${${variableString}}`, getVariableValue(variableString, inputs.data));
}

return exits.success(inputs.command);

return exits.success(inputs.command.toString().replace(/\$\{([^}]+)\}/g, function(match, group1, offset, wholeString) {
return _.get(inputs.data, group1, match);
}));
}


};

function replaceAllInString(string, valueToReplace, newValue) {
return string.split(valueToReplace).join(newValue);
}

// Find variables denoted like ${x} and ${y} and returns an array of strings like [x, y]
function findVariables(command) {
let startIdx = 0;
const foundVariables = [];

while (startIdx < command.length) {
let x = command.indexOf('${', startIdx);
let y = command.indexOf('}', x);

if (y !== -1 && x !== -1) {
// Variable found!
startIdx = y;
foundVariables.push(command.substring(x + 2, y));
} else {
// No more variables in the string, exit the loop
startIdx = command.length + 1;
}

}

return foundVariables;
}

// Input a string like "player.name" and returns the value for that (nested) property from inputs.data
function getVariableValue(variableString, data) {
let propertyArray = variableString.split('.');
if (propertyArray.length === 1) {
return data[propertyArray[0]];
} else {
return getVariableValue(propertyArray.slice(1).join('.'), data[propertyArray[0]]);
}

}
49 changes: 29 additions & 20 deletions api/hooks/bannedItems/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const Sentry = require('@sentry/node');

module.exports = function banneditems(sails) {
return {
initialize: function(cb) {
Expand Down Expand Up @@ -46,33 +48,40 @@ module.exports = function banneditems(sails) {

async function handleItemTrackerUpdate(data) {
const { server, trackingInfo } = data;
const config = server.config[0];
const config = server.config[0] || {};
const { bannedItems, bannedItemsCommand } = config;
const bannedItemsSet = new Set(JSON.parse(bannedItems));

for (const onlinePlayer of trackingInfo) {
if (onlinePlayer.inventory) {
if (!Array.isArray(onlinePlayer.inventory)) {
onlinePlayer.inventory = JSON.parse(onlinePlayer.inventory);
}
try {
const bannedItemsSet = new Set(JSON.parse(bannedItems));
for (const onlinePlayer of trackingInfo) {
if (onlinePlayer.inventory) {
if (!Array.isArray(onlinePlayer.inventory)) {
onlinePlayer.inventory = JSON.parse(onlinePlayer.inventory);
}

const playerItemsSet = new Set(onlinePlayer.inventory.map(e => e.name));
const unionOfSets = intersection(playerItemsSet, bannedItemsSet);
if (unionOfSets.size) {
const isImmune = await sails.helpers.roles.checkPermission.with({
serverId: server.id,
playerId: onlinePlayer.player,
permission: "immuneToBannedItemsList"
});
const playerItemsSet = new Set(onlinePlayer.inventory.map(e => e.name));
const unionOfSets = intersection(playerItemsSet, bannedItemsSet);
if (unionOfSets.size) {
const isImmune = await sails.helpers.roles.checkPermission.with({
serverId: server.id,
playerId: onlinePlayer.player,
permission: "immuneToBannedItemsList"
});

if (!isImmune.hasPermission) {
sails.log.info(
`Detected banned item(s) on player ${onlinePlayer.player} from server ${onlinePlayer.server}`
);
executePunishment(onlinePlayer.player, server, config);
if (!isImmune.hasPermission) {
sails.log.info(
`Detected banned item(s) on player ${onlinePlayer.player} from server ${onlinePlayer.server}`
);
executePunishment(onlinePlayer.player, server, config);
}
}
}
}
} catch (e) {
Sentry.withScope(function(scope) {
scope.setTag('serverId', server.id);
Sentry.captureMessage(e);
});
}
}

Expand Down
2 changes: 1 addition & 1 deletion api/hooks/customDiscordNotification/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ async function sendNotification(logLine, server, customNotif) {

embed.setTitle(`Custom notification for ${server.name}`)
.addField('Time', logLine.time, true)
.addField('Message', logLine.msg)
.addField('Message', logLine.msg.substr(0, 1024))
.addField('Triggered by', customNotif.stringToSearchFor)
channel.send(embed);
}
Expand Down
4 changes: 4 additions & 0 deletions api/hooks/discordChatBridge/chatBridgeChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ class ChatBridgeChannel {
async sendRichConnectedMessageToDiscord(connectedMsg) {
let connectedPlayer = connectedMsg.player;

if (!connectedPlayer) {
return;
}

let gblBans = await BanEntry.find({
steamId: connectedPlayer.steamId
});
Expand Down
98 changes: 98 additions & 0 deletions api/hooks/sentry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
module.exports = function Sentry(sails) {
return {
/**
* Default configuration
*
* We do this in a function since the configuration key for
* the hook is itself configurable, so we can't just return
* an object.
*/
defaults: {
__configKey__: {
dsn: process.env.SENTRY_DSN,
options: {
environment: process.env.NODE_ENV || 'development'
}
}
},

/**
* Initialize the hook
* @param {Function} cb Callback for when we're done initializing
* @return {Function} cb Callback for when we're done initializing
*/
initialize: function(cb) {
var settings = sails.config[this.configKey];

if (!settings.dsn) {
sails.log.verbose('DSN for Sentry is required.');
return cb();
}

const Sentry = require('@sentry/node');
const { getCurrentHub } = require('@sentry/core');
const { Severity } = require('@sentry/types');
const util = require('util');

Sentry.init(settings);

sails.sentry = Sentry;

const origServerError = sails.hooks.responses.middleware.serverError;
sails.hooks.responses.middleware.serverError = function(err) {
Sentry.captureException(err);
origServerError.bind(this)(...arguments);
}

for (const level of Object.keys(sails.log)) {
switch (level) {
case 'verbose':
case 'silly':
case 'blank':
case 'ship':
continue;

case 'debug':
sentryLevel = Severity.Debug;
break;
case 'crit':
case 'error':
sentryLevel = Severity.Error;
break;
case 'info':
sentryLevel = Severity.Info;
break;
case 'warn':
sentryLevel = Severity.Warning;
break;
default:
throw new Error('not sure what to do with ' + level);
}
const origFunction = sails.log[level].bind(sails.log);
sails.log[level] = function() {
getCurrentHub().addBreadcrumb(
{
category: 'sailslog',
level: sentryLevel,
message: util.format.apply(undefined, arguments),
},
{
input: [...arguments],
level,
},
);
origFunction(...arguments);
}
}

// handles Bluebird's promises unhandled rejections
process.on('unhandledRejection', function(reason) {
console.error('Unhandled rejection:', reason);
Sentry.captureException(reason);
});

// We're done initializing.
return cb();
}
};
};
4 changes: 0 additions & 4 deletions config/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ var passport = require('passport');
var SteamStrategy = require('passport-steam');
var DiscordStrategy = require('passport-discord').Strategy;
const Sentry = require('@sentry/node');
Sentry.init({
dsn: process.env.SENTRY_DSN
});


var maxAge = 900;
/**
Expand Down
7 changes: 7 additions & 0 deletions config/sentry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports.sentry = {
active: !!process.env.SENTRY_DSN,
dsn: process.env.SENTRY_DSN,
options: {
environment: process.env.NODE_ENV || 'development'
}
};
17 changes: 17 additions & 0 deletions test/integration/hooks/discordChatBridge/chatBridgeChannel.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const expect = require("chai").expect;
const sinon = require('sinon');
const ChatBridgeChannel = require("../../../../api/hooks/discordChatBridge/chatBridgeChannel");

describe('ChatBridgeChannel', function () {
it('Doesnt try to do anything when non player connects', async function () {
sinon.stub(sails.hooks.sdtdlogs, "getLoggingObject").callsFake(async () => null);
sinon.stub(ChatBridgeChannel.prototype, "start").callsFake(async () => null);

const textChannel = {};
const cbc = new ChatBridgeChannel(textChannel, sails.testServer);
await cbc.sendRichConnectedMessageToDiscord({
player: undefined
});
});
});

21 changes: 21 additions & 0 deletions test/unit/helpers/sdtd/fill-custom-variables.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const chai = require('chai');
const expect = chai.expect;
const chaiAsPromised = require("chai-as-promised");

chai.use(chaiAsPromised);

describe('HELPER sdtd/fill-custom-variables', () => {
it('silently works when undefined data is provided', async () => {
const result = await sails.helpers.sdtd.fillCustomVariables('whoa there ${player.friendlyName}', {} );
expect(result).to.be.eql('whoa there ${player.friendlyName}');
});
it('simple replacements work', async () => {
const result = await sails.helpers.sdtd.fillCustomVariables('whoa there ${friendlyName}', { friendlyName: 'halkeye' } );
expect(result).to.be.eql('whoa there halkeye');
});
it('nested replacements work', async () => {
const result = await sails.helpers.sdtd.fillCustomVariables('whoa there ${player.friendlyName}', { player: { friendlyName: 'halkeye' } } );
expect(result).to.be.eql('whoa there halkeye');
});
});

0 comments on commit 5780557

Please sign in to comment.