From 682d3070e946b48ce14e124fe8a669b81506e375 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Thu, 15 Mar 2018 10:37:05 +0200 Subject: [PATCH] Move IRC object and validation to network model --- src/client.js | 100 +++++----------------------------------- src/models/network.js | 105 ++++++++++++++++++++++++++++++++++++++++++ src/server.js | 48 +++++++++++++++---- 3 files changed, 156 insertions(+), 97 deletions(-) diff --git a/src/client.js b/src/client.js index 76562aa8..bc90a7f8 100644 --- a/src/client.js +++ b/src/client.js @@ -2,12 +2,10 @@ const _ = require("lodash"); const colors = require("chalk"); -const pkg = require("../package.json"); const Chan = require("./models/chan"); const crypto = require("crypto"); const Msg = require("./models/msg"); const Network = require("./models/network"); -const ircFramework = require("irc-framework"); const Helper = require("./helper"); const UAParser = require("ua-parser-js"); const MessageStorage = require("./plugins/sqlite"); @@ -140,8 +138,6 @@ Client.prototype.find = function(channelId) { Client.prototype.connect = function(args) { const client = this; - const nick = args.nick || "thelounge"; - let webirc = null; let channels = []; if (args.channels) { @@ -176,105 +172,33 @@ Client.prototype.connect = function(args) { }); } - args.ip = args.ip || (client.config && client.config.ip) || client.ip; - args.hostname = args.hostname || (client.config && client.config.hostname) || client.hostname; - const network = new Network({ uuid: args.uuid, - name: args.name || (Helper.config.displayNetwork ? "" : Helper.config.defaults.name) || "", - host: args.host || "", - port: parseInt(args.port, 10) || (args.tls ? 6697 : 6667), + name: String(args.name || (Helper.config.displayNetwork ? "" : Helper.config.defaults.name) || ""), + host: String(args.host || ""), + port: parseInt(args.port, 10), tls: !!args.tls, rejectUnauthorized: !!args.rejectUnauthorized, - password: args.password, - username: args.username || nick.replace(/[^a-zA-Z0-9]/g, ""), - realname: args.realname || "The Lounge User", - commands: args.commands, - ip: args.ip, - hostname: args.hostname, + password: String(args.password || ""), + nick: String(args.nick || ""), + username: String(args.username || ""), + realname: String(args.realname || ""), + commands: args.commands || [], + ip: args.ip || (client.config && client.config.ip) || client.ip, + hostname: args.hostname || (client.config && client.config.hostname) || client.hostname, channels: channels, }); - network.setNick(nick); client.networks.push(network); client.emit("network", { networks: [network.getFilteredClone(this.lastActiveChannel, -1)], }); - if (Helper.config.lockNetwork) { - // This check is needed to prevent invalid user configurations - if (!Helper.config.public && args.host && args.host.length > 0 && args.host !== Helper.config.defaults.host) { - network.channels[0].pushMessage(client, new Msg({ - type: Msg.Type.ERROR, - text: "Hostname you specified is not allowed.", - }), true); - return; - } - - network.host = Helper.config.defaults.host; - network.port = Helper.config.defaults.port; - network.tls = Helper.config.defaults.tls; - network.rejectUnauthorized = Helper.config.defaults.rejectUnauthorized; - } - - if (network.host.length === 0) { - network.channels[0].pushMessage(client, new Msg({ - type: Msg.Type.ERROR, - text: "You must specify a hostname to connect.", - }), true); + if (!network.validate(client)) { return; } - if (Helper.config.webirc && network.host in Helper.config.webirc) { - if (!args.hostname) { - args.hostname = args.ip; - } - - if (args.ip) { - if (Helper.config.webirc[network.host] instanceof Function) { - webirc = Helper.config.webirc[network.host](client, args); - } else { - webirc = { - password: Helper.config.webirc[network.host], - username: pkg.name, - address: args.ip, - hostname: args.hostname, - }; - } - } else { - log.warn("Cannot find a valid WEBIRC configuration for " + nick - + "!" + network.username + "@" + network.host); - } - } - - network.irc = new ircFramework.Client({ - version: false, // We handle it ourselves - host: network.host, - port: network.port, - nick: nick, - username: Helper.config.useHexIp ? Helper.ip2hex(args.ip) : network.username, - gecos: network.realname, - password: network.password, - tls: network.tls, - outgoing_addr: Helper.config.bind, - rejectUnauthorized: network.rejectUnauthorized, - enable_chghost: true, - enable_echomessage: true, - auto_reconnect: true, - auto_reconnect_wait: 10000 + Math.floor(Math.random() * 1000), // If multiple users are connected to the same network, randomize their reconnections a little - auto_reconnect_max_retries: 360, // At least one hour (plus timeouts) worth of reconnections - webirc: webirc, - }); - - network.irc.requestCap([ - "znc.in/self-message", // Legacy echo-message for ZNC - ]); - - // Request only new messages from ZNC if we have sqlite logging enabled - // See http://wiki.znc.in/Playback - if (client.config.log && Helper.config.messageStorage.includes("sqlite")) { - network.irc.requestCap("znc.in/playback"); - } + network.createIrcFramework(client); events.forEach((plugin) => { require(`./plugins/irc-events/${plugin}`).apply(client, [ diff --git a/src/models/network.js b/src/models/network.js index f3c2a28b..5696a5ee 100644 --- a/src/models/network.js +++ b/src/models/network.js @@ -2,7 +2,10 @@ const _ = require("lodash"); const uuidv4 = require("uuid/v4"); +const IrcFramework = require("irc-framework"); const Chan = require("./chan"); +const Msg = require("./msg"); +const Helper = require("../helper"); module.exports = Network; @@ -59,6 +62,108 @@ function Network(attr) { ); } +Network.prototype.validate = function(client) { + this.setNick(String(this.nick || "thelounge").replace(" ", "_")); + + if (!this.username) { + this.username = this.nick.replace(/[^a-zA-Z0-9]/g, ""); + } + + if (!this.realname) { + this.realname = "The Lounge User"; + } + + if (!this.port) { + this.port = this.tls ? 6697 : 6667; + } + + if (Helper.config.lockNetwork) { + // This check is needed to prevent invalid user configurations + if (!Helper.config.public && this.host && this.host.length > 0 && this.host !== Helper.config.defaults.host) { + this.channels[0].pushMessage(client, new Msg({ + type: Msg.Type.ERROR, + text: "Hostname you specified is not allowed.", + }), true); + + return false; + } + + this.host = Helper.config.defaults.host; + this.port = Helper.config.defaults.port; + this.tls = Helper.config.defaults.tls; + this.rejectUnauthorized = Helper.config.defaults.rejectUnauthorized; + } + + if (this.host.length === 0) { + this.channels[0].pushMessage(client, new Msg({ + type: Msg.Type.ERROR, + text: "You must specify a hostname to connect.", + }), true); + + return false; + } + + return true; +}; + +Network.prototype.createIrcFramework = function(client) { + this.irc = new IrcFramework.Client({ + version: false, // We handle it ourselves + host: this.host, + port: this.port, + nick: this.nick, + username: Helper.config.useHexIp ? Helper.ip2hex(this.ip) : this.username, + gecos: this.realname, + password: this.password, + tls: this.tls, + outgoing_addr: Helper.config.bind, + rejectUnauthorized: this.rejectUnauthorized, + enable_chghost: true, + enable_echomessage: true, + auto_reconnect: true, + auto_reconnect_wait: 10000 + Math.floor(Math.random() * 1000), // If multiple users are connected to the same network, randomize their reconnections a little + auto_reconnect_max_retries: 360, // At least one hour (plus timeouts) worth of reconnections + webirc: this.createWebIrc(client), + }); + + this.irc.requestCap([ + "znc.in/self-message", // Legacy echo-message for ZNC + ]); + + // Request only new messages from ZNC if we have sqlite logging enabled + // See http://wiki.znc.in/Playback + if (client.config.log && Helper.config.messageStorage.includes("sqlite")) { + this.irc.requestCap("znc.in/playback"); + } +}; + +Network.prototype.createWebIrc = function(client) { + if (!Helper.config.webirc || !(this.host in Helper.config.webirc)) { + return null; + } + + if (!this.ip) { + log.warn(`Cannot find a valid WEBIRC configuration for ${this.nick}!${this.username}@${this.host}`); + + return null; + } + + if (!this.hostname) { + this.hostname = this.ip; + } + + if (Helper.config.webirc[this.host] instanceof Function) { + return Helper.config.webirc[this.host](client, this); + } + + return { + password: Helper.config.webirc[this.host], + username: "thelounge", + address: this.ip, + hostname: this.hostname, + }; +}; + Network.prototype.destroy = function() { this.channels.forEach((channel) => channel.destroy()); }; diff --git a/src/server.js b/src/server.js index 0971fb9c..f859bf62 100644 --- a/src/server.js +++ b/src/server.js @@ -307,11 +307,40 @@ function initializeClient(socket, client, token, lastMessage) { data.ip = null; data.hostname = null; data.uuid = null; + data.commands = null; client.connect(data); } }); + socket.on("network:get", (data) => { + if (typeof data !== "string") { + return; + } + + const network = _.find(client.networks, {uuid: data}); + + if (!network) { + return; + } + + socket.emit("network:info", getClientConfiguration(network.export())); + }); + + socket.on("network:edit", (data) => { + if (typeof data !== "object") { + return; + } + + const network = _.find(client.networks, {uuid: data.uuid}); + + if (!network) { + return; + } + + network.edit(client, data); + }); + if (!Helper.config.public && !Helper.config.ldap.enable) { socket.on("change-password", (data) => { if (typeof data === "object") { @@ -541,27 +570,22 @@ function initializeClient(socket, client, token, lastMessage) { } } -function getClientConfiguration() { +function getClientConfiguration(network) { const config = _.pick(Helper.config, [ "public", "lockNetwork", "displayNetwork", "useHexIp", - "themes", "prefetch", ]); config.ldapEnabled = Helper.config.ldap.enable; - config.version = pkg.version; - config.gitCommit = Helper.getGitCommit(); - config.themes = themes.getAll(); - config.defaultTheme = Helper.config.theme; if (config.displayNetwork) { - config.defaults = _.clone(Helper.config.defaults); + config.defaults = _.clone(network || Helper.config.defaults); } else { // Only send defaults that are visible on the client - config.defaults = _.pick(Helper.config.defaults, [ + config.defaults = _.pick(network || Helper.config.defaults, [ "nick", "username", "password", @@ -570,7 +594,13 @@ function getClientConfiguration() { ]); } - config.defaults.nick = config.defaults.nick.replace(/%/g, () => Math.floor(Math.random() * 10)); + if (!network) { + config.version = pkg.version; + config.gitCommit = Helper.getGitCommit(); + config.themes = themes.getAll(); + config.defaultTheme = Helper.config.theme; + config.defaults.nick = config.defaults.nick.replace(/%/g, () => Math.floor(Math.random() * 10)); + } return config; }