Merge pull request #3307 from thelounge/xpaw/browser-object

Store ip and language in a separate object in user file
This commit is contained in:
Pavel Djundik 2019-07-19 13:11:20 +03:00 committed by GitHub
commit 7e5c2672b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 66 additions and 80 deletions

View file

@ -298,23 +298,23 @@ module.exports = {
// //
// ```json // ```json
// webirc: { // webirc: {
// "irc.example.net": "password1", // "irc.example.net": "thisiswebircpassword1",
// "irc.example.org": "passw0rd", // "irc.example.org": "thisiswebircpassword2",
// }, // },
// ``` // ```
// //
// - **Advanced**: an object where keys are IRC hosts and values are functions // - **Advanced**: an object where keys are IRC hosts and values are functions
// that take three arguments (`client`, `args`, `trusted`) and return an // that take two arguments (`webircObj`, `network`) and return an
// object to be directly passed to `irc-framework`. For example: // object to be directly passed to `irc-framework`. `webircObj` contains the
// generated object which you can modify. For example:
// //
// ```js // ```js
// webirc: { // webirc: {
// "irc.example.net": (client, args, trusted) => ({ // "irc.example.com": (webircObj, network) => {
// username: "thelounge", // webircObj.password = "thisiswebircpassword";
// password: "password1", // webircObj.hostname = `webirc/${webircObj.hostname}`;
// address: args.ip, // return webircObj;
// hostname: `webirc/${args.hostname}` // },
// }),
// }, // },
// ``` // ```
// //

View file

@ -92,6 +92,10 @@ function Client(manager, name, config = {}) {
client.config.clientSettings = {}; client.config.clientSettings = {};
} }
if (typeof client.config.browser !== "object") {
client.config.browser = {};
}
client.compileCustomHighlights(); client.compileCustomHighlights();
_.forOwn(client.config.sessions, (session) => { _.forOwn(client.config.sessions, (session) => {
@ -195,8 +199,6 @@ Client.prototype.connect = function(args) {
username: String(args.username || ""), username: String(args.username || ""),
realname: String(args.realname || ""), realname: String(args.realname || ""),
commands: args.commands || [], 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, channels: channels,
ignoreList: args.ignoreList ? args.ignoreList : [], ignoreList: args.ignoreList ? args.ignoreList : [],
}); });
@ -547,7 +549,6 @@ Client.prototype.quit = function(signOut) {
Client.prototype.clientAttach = function(socketId, token) { Client.prototype.clientAttach = function(socketId, token) {
const client = this; const client = this;
let save = false;
if (client.awayMessage && _.size(client.attachedClients) === 0) { if (client.awayMessage && _.size(client.attachedClients) === 0) {
client.networks.forEach(function(network) { client.networks.forEach(function(network) {
@ -561,27 +562,6 @@ Client.prototype.clientAttach = function(socketId, token) {
const openChannel = client.lastActiveChannel; const openChannel = client.lastActiveChannel;
client.attachedClients[socketId] = {token, openChannel}; client.attachedClients[socketId] = {token, openChannel};
// Update old networks to store ip and hostmask
client.networks.forEach((network) => {
if (!network.ip) {
save = true;
network.ip = (client.config && client.config.ip) || client.ip;
}
if (!network.hostname) {
const hostmask = (client.config && client.config.hostname) || client.hostname;
if (hostmask) {
save = true;
network.hostmask = hostmask;
}
}
});
if (save) {
client.save();
}
}; };
Client.prototype.clientDetach = function(socketId) { Client.prototype.clientDetach = function(socketId) {

View file

@ -118,6 +118,7 @@ ClientManager.prototype.addUser = function(name, password, enableLog) {
networks: [], networks: [],
sessions: {}, sessions: {},
clientSettings: {}, clientSettings: {},
browser: {},
}; };
try { try {

View file

@ -1,7 +1,6 @@
"use strict"; "use strict";
const _ = require("lodash"); const _ = require("lodash");
const log = require("../log");
const uuidv4 = require("uuid/v4"); const uuidv4 = require("uuid/v4");
const IrcFramework = require("irc-framework"); const IrcFramework = require("irc-framework");
const Chan = require("./chan"); const Chan = require("./chan");
@ -36,8 +35,6 @@ function Network(attr) {
username: "", username: "",
realname: "", realname: "",
channels: [], channels: [],
ip: null,
hostname: null,
irc: null, irc: null,
serverOptions: { serverOptions: {
CHANTYPES: ["#", "&"], CHANTYPES: ["#", "&"],
@ -125,7 +122,7 @@ Network.prototype.createIrcFramework = function(client) {
host: this.host, host: this.host,
port: this.port, port: this.port,
nick: this.nick, nick: this.nick,
username: Helper.config.useHexIp ? Helper.ip2hex(this.ip) : this.username, username: Helper.config.useHexIp ? Helper.ip2hex(client.config.browser.ip) : this.username,
gecos: this.realname, gecos: this.realname,
password: this.password, password: this.password,
tls: this.tls, tls: this.tls,
@ -156,26 +153,19 @@ Network.prototype.createWebIrc = function(client) {
return null; return null;
} }
if (!this.ip) { const webircObject = {
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 (typeof Helper.config.webirc[this.host] === "function") {
return Helper.config.webirc[this.host](client, this);
}
return {
password: Helper.config.webirc[this.host], password: Helper.config.webirc[this.host],
username: "thelounge", username: "thelounge",
address: this.ip, address: client.config.browser.ip,
hostname: this.hostname, hostname: client.config.browser.hostname,
}; };
if (typeof Helper.config.webirc[this.host] === "function") {
webircObject.password = null;
return Helper.config.webirc[this.host](webircObject, this);
}
return webircObject;
}; };
Network.prototype.edit = function(client, args) { Network.prototype.edit = function(client, args) {
@ -348,8 +338,6 @@ Network.prototype.export = function() {
"username", "username",
"realname", "realname",
"commands", "commands",
"ip",
"hostname",
"ignoreList", "ignoreList",
]); ]);

View file

@ -79,7 +79,7 @@ module.exports = function(irc, network) {
let ident = client.name || network.username; let ident = client.name || network.username;
if (Helper.config.useHexIp) { if (Helper.config.useHexIp) {
ident = Helper.ip2hex(network.ip); ident = Helper.ip2hex(client.config.browser.ip);
} }
identSocketId = client.manager.identHandler.addSocket(socket, ident); identSocketId = client.manager.identHandler.addSocket(socket, ident);

View file

@ -63,7 +63,7 @@ module.exports = function(client, chan, msg) {
fetch(url, { fetch(url, {
accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
language: client.language, language: client.config.browser.language,
}).then((res) => { }).then((res) => {
parse(msg, chan, preview, res, client); parse(msg, chan, preview, res, client);
}).catch((err) => { }).catch((err) => {
@ -106,7 +106,7 @@ function parseHtml(preview, res, client) {
// Verify that thumbnail pic exists and is under allowed size // Verify that thumbnail pic exists and is under allowed size
if (preview.thumb.length) { if (preview.thumb.length) {
fetch(preview.thumb, {language: client.language}).then((resThumb) => { fetch(preview.thumb, {language: client.config.browser.language}).then((resThumb) => {
if (resThumb === null if (resThumb === null
|| !(imageTypeRegex.test(resThumb.type)) || !(imageTypeRegex.test(resThumb.type))
|| resThumb.size > (Helper.config.prefetchMaxImageSize * 1024)) { || resThumb.size > (Helper.config.prefetchMaxImageSize * 1024)) {
@ -155,7 +155,7 @@ function parseHtmlMedia($, preview, client) {
accept: type === "video" ? accept: type === "video" ?
"video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5" : "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5" :
"audio/webm, audio/ogg, audio/wav, audio/*;q=0.9, application/ogg;q=0.7, video/*;q=0.6; */*;q=0.5", "audio/webm, audio/ogg, audio/wav, audio/*;q=0.9, application/ogg;q=0.7, video/*;q=0.6; */*;q=0.5",
language: client.language, language: client.config.browser.language,
}).then((resMedia) => { }).then((resMedia) => {
if (resMedia === null || !mediaTypeRegex.test(resMedia.type)) { if (resMedia === null || !mediaTypeRegex.test(resMedia.type)) {
return reject(); return reject();

View file

@ -235,7 +235,7 @@ function getClientIp(socket) {
let ip = socket.handshake.address || "127.0.0.1"; let ip = socket.handshake.address || "127.0.0.1";
if (Helper.config.reverseProxy) { if (Helper.config.reverseProxy) {
const forwarded = (socket.request.headers["x-forwarded-for"] || "").split(/\s*,\s*/).filter(Boolean); const forwarded = (socket.handshake.headers["x-forwarded-for"] || "").split(/\s*,\s*/).filter(Boolean);
if (forwarded.length && net.isIP(forwarded[0])) { if (forwarded.length && net.isIP(forwarded[0])) {
ip = forwarded[0]; ip = forwarded[0];
@ -245,6 +245,16 @@ function getClientIp(socket) {
return ip.replace(/^::ffff:/, ""); return ip.replace(/^::ffff:/, "");
} }
function getClientSecure(socket) {
let secure = socket.handshake.secure;
if (Helper.config.reverseProxy && socket.handshake.headers["x-forwarded-proto"] === "https") {
secure = true;
}
return secure;
}
function allRequests(req, res, next) { function allRequests(req, res, next) {
res.setHeader("X-Content-Type-Options", "nosniff"); res.setHeader("X-Content-Type-Options", "nosniff");
return next(); return next();
@ -329,8 +339,6 @@ function initializeClient(socket, client, token, lastMessage) {
socket.on("network:new", (data) => { socket.on("network:new", (data) => {
if (typeof data === "object") { if (typeof data === "object") {
// prevent people from overriding webirc settings // prevent people from overriding webirc settings
data.ip = null;
data.hostname = null;
data.uuid = null; data.uuid = null;
data.commands = null; data.commands = null;
data.ignoreList = null; data.ignoreList = null;
@ -657,21 +665,32 @@ function performAuthentication(data) {
let client; let client;
let token = null; let token = null;
const finalInit = () => initializeClient(socket, client, token, data.lastMessage || -1); const finalInit = () => {
initializeClient(socket, client, token, data.lastMessage || -1);
if (!Helper.config.public) {
client.manager.updateUser(client.name, {
browser: client.config.browser,
});
}
};
const initClient = () => { const initClient = () => {
socket.emit("configuration", getClientConfiguration()); socket.emit("configuration", getClientConfiguration());
client.ip = getClientIp(socket); client.config.browser = {
client.language = getClientLanguage(socket); ip: getClientIp(socket),
isSecure: getClientSecure(socket),
language: getClientLanguage(socket),
};
// If webirc is enabled perform reverse dns lookup // If webirc is enabled perform reverse dns lookup
if (Helper.config.webirc === null) { if (Helper.config.webirc === null) {
return finalInit(); return finalInit();
} }
reverseDnsLookup(client.ip, (hostname) => { reverseDnsLookup(client.config.browser.ip, (hostname) => {
client.hostname = hostname; client.config.browser.hostname = hostname;
finalInit(); finalInit();
}); });

View file

@ -39,8 +39,6 @@ describe("Network", function() {
realname: "", realname: "",
commands: [], commands: [],
nick: "chillin`", nick: "chillin`",
ip: null,
hostname: null,
channels: [ channels: [
{name: "#thelounge", key: ""}, {name: "#thelounge", key: ""},
{name: "&foobar", key: ""}, {name: "&foobar", key: ""},
@ -127,8 +125,8 @@ describe("Network", function() {
expect(saveCalled).to.be.true; expect(saveCalled).to.be.true;
expect(network.guid).to.not.equal("newGuid"); expect(network.guid).to.not.equal("newGuid");
expect(network.ip).to.be.null; expect(network.ip).to.be.undefined;
expect(network.hostname).to.be.null; expect(network.hostname).to.be.undefined;
expect(network.name).to.equal("Lounge Test Network"); expect(network.name).to.equal("Lounge Test Network");
expect(network.channels[0].name).to.equal("Lounge Test Network"); expect(network.channels[0].name).to.equal("Lounge Test Network");
@ -226,8 +224,6 @@ describe("Network", function() {
"channels", "channels",
"commands", "commands",
"host", "host",
"hostname",
"ip",
"name", "name",
"port", "port",
"realname", "realname",

View file

@ -287,7 +287,7 @@ describe("Link plugin", function() {
it("should use client's preferred language as Accept-Language header", function(done) { it("should use client's preferred language as Accept-Language header", function(done) {
const language = "sv,en-GB;q=0.9,en;q=0.8"; const language = "sv,en-GB;q=0.9,en;q=0.8";
this.irc.language = language; this.irc.config.browser.language = language;
app.get("/language-check", function(req, res) { app.get("/language-check", function(req, res) {
expect(req.headers["accept-language"]).to.equal(language); expect(req.headers["accept-language"]).to.equal(language);
@ -449,7 +449,7 @@ describe("Link plugin", function() {
let requests = 0; let requests = 0;
let responses = 0; let responses = 0;
this.irc.language = "very nice language"; this.irc.config.browser.language = "very nice language";
link(this.irc, this.network.channels[0], message); link(this.irc, this.network.channels[0], message);
link(this.irc, this.network.channels[0], message); link(this.irc, this.network.channels[0], message);
@ -489,11 +489,11 @@ describe("Link plugin", function() {
const requests = []; const requests = [];
let responses = 0; let responses = 0;
this.irc.language = "first language"; this.irc.config.browser.language = "first language";
link(this.irc, this.network.channels[0], message); link(this.irc, this.network.channels[0], message);
setTimeout(() => { setTimeout(() => {
this.irc.language = "second language"; this.irc.config.browser.language = "second language";
link(this.irc, this.network.channels[0], message); link(this.irc, this.network.channels[0], message);
}, 100); }, 100);

View file

@ -8,7 +8,9 @@ const Network = require("../src/models/network");
const Chan = require("../src/models/chan"); const Chan = require("../src/models/chan");
function MockClient() { function MockClient() {
this.user = {nick: "test-user"}; this.config = {
browser: {},
};
} }
util.inherits(MockClient, EventEmitter); util.inherits(MockClient, EventEmitter);