From 5a9b3128d1878fc0f15004e1e547620276820d6d Mon Sep 17 00:00:00 2001 From: Calvin Montgomery Date: Mon, 15 Jul 2013 23:01:12 -0400 Subject: [PATCH] I think it works --- acp.js | 284 ++++++++++++++++++++++++++--------------------------- channel.js | 58 +++++------ server.js | 8 +- user.js | 67 +++---------- 4 files changed, 189 insertions(+), 228 deletions(-) diff --git a/acp.js b/acp.js index 3faee08b..d324cb9b 100644 --- a/acp.js +++ b/acp.js @@ -9,159 +9,159 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -var Server = require("./server"); var Auth = require("./auth"); -var Database = require("./database"); var ActionLog = require("./actionlog"); -module.exports = { - init: function(user) { - ActionLog.record(user.ip, user.name, "acp-init"); - user.socket.on("acp-announce", function(data) { - ActionLog.record(user.ip, user.name, "acp-announce", data); - Server.announcement = data; - Server.io.sockets.emit("announcement", data); - }); +module.exports = function (Server) { + return { + init: function(user) { + ActionLog.record(user.ip, user.name, "acp-init"); + user.socket.on("acp-announce", function(data) { + ActionLog.record(user.ip, user.name, "acp-announce", data); + Server.announcement = data; + Server.io.sockets.emit("announcement", data); + }); - user.socket.on("acp-announce-clear", function() { - ActionLog.record(user.ip, user.name, "acp-announce-clear"); - Server.announcement = null; - }); + user.socket.on("acp-announce-clear", function() { + ActionLog.record(user.ip, user.name, "acp-announce-clear"); + Server.announcement = null; + }); - user.socket.on("acp-global-ban", function(data) { - ActionLog.record(user.ip, user.name, "acp-global-ban", data.ip); - Database.globalBanIP(data.ip, data.note); - user.socket.emit("acp-global-banlist", Database.refreshGlobalBans()); - }); + user.socket.on("acp-global-ban", function(data) { + ActionLog.record(user.ip, user.name, "acp-global-ban", data.ip); + Server.db.globalBanIP(data.ip, data.note); + user.socket.emit("acp-global-banlist", Server.db.refreshGlobalBans()); + }); - user.socket.on("acp-global-unban", function(ip) { - ActionLog.record(user.ip, user.name, "acp-global-unban", ip); - Database.globalUnbanIP(ip); - user.socket.emit("acp-global-banlist", Database.refreshGlobalBans()); - }); + user.socket.on("acp-global-unban", function(ip) { + ActionLog.record(user.ip, user.name, "acp-global-unban", ip); + Server.db.globalUnbanIP(ip); + user.socket.emit("acp-global-banlist", Server.db.refreshGlobalBans()); + }); - user.socket.emit("acp-global-banlist", Database.refreshGlobalBans()); + user.socket.emit("acp-global-banlist", Server.db.refreshGlobalBans()); - user.socket.on("acp-lookup-user", function(name) { - var db = Database.getConnection(); - if(!db) { - return; - } - - var query = Database.createQuery( - "SELECT id,uname,global_rank,profile_image,profile_text,email FROM registrations WHERE uname LIKE ?", - ["%"+name+"%"] - ); - - var res = db.querySync(query); - if(!res) - return; - - var rows = res.fetchAllSync(); - user.socket.emit("acp-userdata", rows); - }); - - user.socket.on("acp-reset-password", function(data) { - if(Auth.getGlobalRank(data.name) >= user.global_rank) - return; - try { - var hash = Database.generatePasswordReset(user.ip, data.name, data.email); - ActionLog.record(user.ip, user.name, "acp-reset-password", data.name); - } - catch(e) { - user.socket.emit("acp-reset-password", { - success: false, - error: e - }); - return; - } - if(hash) { - user.socket.emit("acp-reset-password", { - success: true, - hash: hash - }); - } - else { - user.socket.emit("acp-reset-password", { - success: false, - error: "Reset failed" - }); - } - - }); - - user.socket.on("acp-set-rank", function(data) { - if(data.rank < 1 || data.rank >= user.global_rank) - return; - - if(Auth.getGlobalRank(data.name) >= user.global_rank) - return; - - var db = Database.getConnection(); - if(!db) - return; - - ActionLog.record(user.ip, user.name, "acp-set-rank", data); - var query = Database.createQuery( - "UPDATE registrations SET global_rank=? WHERE uname=?", - [data.rank, data.name] - ); - - var res = db.querySync(query); - if(!res) - return; - - user.socket.emit("acp-set-rank", data); - }); - - user.socket.on("acp-list-loaded", function() { - var chans = []; - var all = Server.getAllChannels(); - for(var c in all) { - var chan = all[c]; - if(!chan) - continue; - - chans.push({ - name: c, - title: chan.opts.pagetitle, - usercount: chan.users.length, - mediatitle: chan.playlist.current ? chan.playlist.current.media.title : "-", - is_public: chan.opts.show_public, - registered: chan.registered - }); - } - - user.socket.emit("acp-list-loaded", chans); - }); - - user.socket.on("acp-channel-unload", function(data) { - if(Server.getChannel(data.name) !== undefined) { - var c = Server.getChannel(data.name); - if(!c) + user.socket.on("acp-lookup-user", function(name) { + var db = Server.db.getConnection(); + if(!db) { return; - ActionLog.record(user.ip, user.name, "acp-channel-unload"); - c.initialized = data.save; - c.users.forEach(function(u) { - c.kick(u, "Channel shutting down"); - }); + } - // At this point c should be unloaded - // if it's still loaded, kill it - c = Server.getChannel(data.name); - if(c !== undefined) - Server.unload(c); - } - }); + var query = Server.db.createQuery( + "SELECT id,uname,global_rank,profile_image,profile_text,email FROM registrations WHERE uname LIKE ?", + ["%"+name+"%"] + ); - user.socket.on("acp-actionlog-clear", function(data) { - ActionLog.clear(data); - ActionLog.record(user.ip, user.name, "acp-actionlog-clear", data); - }); + var res = db.querySync(query); + if(!res) + return; - user.socket.on("acp-actionlog-clear-one", function(data) { - ActionLog.clearOne(data); - ActionLog.record(user.ip, user.name, "acp-actionlog-clear-one", data); - }); + var rows = res.fetchAllSync(); + user.socket.emit("acp-userdata", rows); + }); + + user.socket.on("acp-reset-password", function(data) { + if(Auth.getGlobalRank(data.name) >= user.global_rank) + return; + try { + var hash = Server.db.generatePasswordReset(user.ip, data.name, data.email); + ActionLog.record(user.ip, user.name, "acp-reset-password", data.name); + } + catch(e) { + user.socket.emit("acp-reset-password", { + success: false, + error: e + }); + return; + } + if(hash) { + user.socket.emit("acp-reset-password", { + success: true, + hash: hash + }); + } + else { + user.socket.emit("acp-reset-password", { + success: false, + error: "Reset failed" + }); + } + + }); + + user.socket.on("acp-set-rank", function(data) { + if(data.rank < 1 || data.rank >= user.global_rank) + return; + + if(Auth.getGlobalRank(data.name) >= user.global_rank) + return; + + var db = Server.db.getConnection(); + if(!db) + return; + + ActionLog.record(user.ip, user.name, "acp-set-rank", data); + var query = Server.db.createQuery( + "UPDATE registrations SET global_rank=? WHERE uname=?", + [data.rank, data.name] + ); + + var res = db.querySync(query); + if(!res) + return; + + user.socket.emit("acp-set-rank", data); + }); + + user.socket.on("acp-list-loaded", function() { + var chans = []; + var all = Server.getAllChannels(); + for(var c in all) { + var chan = all[c]; + if(!chan) + continue; + + chans.push({ + name: c, + title: chan.opts.pagetitle, + usercount: chan.users.length, + mediatitle: chan.playlist.current ? chan.playlist.current.media.title : "-", + is_public: chan.opts.show_public, + registered: chan.registered + }); + } + + user.socket.emit("acp-list-loaded", chans); + }); + + user.socket.on("acp-channel-unload", function(data) { + if(Server.getChannel(data.name) !== undefined) { + var c = Server.getChannel(data.name); + if(!c) + return; + ActionLog.record(user.ip, user.name, "acp-channel-unload"); + c.initialized = data.save; + c.users.forEach(function(u) { + c.kick(u, "Channel shutting down"); + }); + + // At this point c should be unloaded + // if it's still loaded, kill it + c = Server.getChannel(data.name); + if(c !== undefined) + Server.unload(c); + } + }); + + user.socket.on("acp-actionlog-clear", function(data) { + ActionLog.clear(data); + ActionLog.record(user.ip, user.name, "acp-actionlog-clear", data); + }); + + user.socket.on("acp-actionlog-clear-one", function(data) { + ActionLog.clearOne(data); + ActionLog.record(user.ip, user.name, "acp-actionlog-clear-one", data); + }); + } } } diff --git a/channel.js b/channel.js index b11b85f7..aea2caeb 100644 --- a/channel.js +++ b/channel.js @@ -11,15 +11,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ var fs = require("fs"); -var Database = require("./database.js"); var Poll = require("./poll.js").Poll; var Media = require("./media.js").Media; var formatTime = require("./media.js").formatTime; var Logger = require("./logger.js"); var InfoGetter = require("./get-info.js"); -var Server = require("./server.js"); -var io = Server.io; -var NWS = require("./notwebsocket"); var Rank = require("./rank.js"); var Auth = require("./auth.js"); var ChatCommand = require("./chatcommand.js"); @@ -28,9 +24,10 @@ var ActionLog = require("./actionlog"); var Playlist = require("./playlist"); var sanitize = require("validator").sanitize; -var Channel = function(name) { +var Channel = function(name, Server) { Logger.syslog.log("Opening channel " + name); this.initialized = false; + this.server = Server; this.name = name; // Initialize defaults @@ -118,7 +115,7 @@ var Channel = function(name) { this.ipkey += "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[parseInt(Math.random() * 65)] } - Database.loadChannel(this); + Server.db.loadChannel(this); if(this.registered) { this.loadDump(); } @@ -303,7 +300,7 @@ Channel.prototype.tryRegister = function(user) { }); } else { - if(Database.registerChannel(this.name, user.name)) { + if(this.server.db.registerChannel(this.name, user.name)) { ActionLog.record(user.ip, user.name, "channel-register-success", this.name); this.registered = true; this.initialized = true; @@ -325,7 +322,7 @@ Channel.prototype.tryRegister = function(user) { } Channel.prototype.unregister = function() { - if(Database.deleteChannel(this.name)) { + if(this.server.db.deleteChannel(this.name)) { this.registered = false; return true; } @@ -337,23 +334,23 @@ Channel.prototype.getRank = function(name) { if(!this.registered) { return global; } - var local = Database.getChannelRank(this.name, name); + var local = this.server.db.getChannelRank(this.name, name); return local > global ? local : global; } Channel.prototype.saveRank = function(user) { - return Database.setChannelRank(this.name, user.name, user.rank); + return this.server.db.setChannelRank(this.name, user.name, user.rank); } Channel.prototype.getIPRank = function(ip) { var names = []; if(!(ip in this.ip_alias)) - this.ip_alias[ip] = Database.getAliases(ip); + this.ip_alias[ip] = this.server.db.getAliases(ip); this.ip_alias[ip].forEach(function(name) { names.push(name); }); - var ranks = Database.getChannelRank(this.name, names); + var ranks = this.server.db.getChannelRank(this.name, names); var rank = 0; for(var i = 0; i < ranks.length; i++) { rank = (ranks[i] > rank) ? ranks[i] : rank; @@ -369,7 +366,7 @@ Channel.prototype.cacheMedia = function(media) { } this.library[media.id] = media; if(this.registered) { - return Database.addToLibrary(this.name, media); + return this.server.db.addToLibrary(this.name, media); } return false; } @@ -403,7 +400,7 @@ Channel.prototype.tryNameBan = function(actor, name) { return false; } - return Database.channelBan(this.name, "*", name, actor.name); + return this.server.db.channelBan(this.name, "*", name, actor.name); } Channel.prototype.unbanName = function(actor, name) { @@ -419,7 +416,7 @@ Channel.prototype.unbanName = function(actor, name) { this.users.forEach(function(u) { chan.sendBanlist(u); }); - return Database.channelUnbanName(this.name, name); + return this.server.db.channelUnbanName(this.name, name); } Channel.prototype.tryIPBan = function(actor, name, range) { @@ -429,7 +426,7 @@ Channel.prototype.tryIPBan = function(actor, name, range) { if(typeof name != "string") { return false; } - var ips = Database.ipForName(name); + var ips = this.server.db.ipForName(name); var chan = this; ips.forEach(function(ip) { if(chan.getIPRank(ip) >= actor.rank) { @@ -461,7 +458,7 @@ Channel.prototype.tryIPBan = function(actor, name, range) { return false; // Update database ban table - return Database.channelBan(chan.name, ip, name, actor.name); + return this.server.db.channelBan(chan.name, ip, name, actor.name); }); var chan = this; @@ -488,7 +485,7 @@ Channel.prototype.banIP = function(actor, receiver) { return false; // Update database ban table - return Database.channelBanIP(this.name, receiver.ip, receiver.name, actor.name); + return this.server.db.channelBanIP(this.name, receiver.ip, receiver.name, actor.name); } Channel.prototype.unbanIP = function(actor, ip) { @@ -506,7 +503,7 @@ Channel.prototype.unbanIP = function(actor, ip) { //this.broadcastBanlist(); // Update database ban table - return Database.channelUnbanIP(this.name, ip); + return this.server.db.channelUnbanIP(this.name, ip); } Channel.prototype.tryUnban = function(actor, data) { @@ -651,7 +648,7 @@ Channel.prototype.userLeave = function(user) { if(this.users.length == 0) { this.logger.log("*** Channel empty, unloading"); var name = this.name; - Server.unload(this); + this.server.unload(this); } } @@ -733,7 +730,7 @@ Channel.prototype.sendRankStuff = function(user) { Channel.prototype.sendChannelRanks = function(user) { if(Rank.hasPermission(user, "acl")) { - user.socket.emit("channelRanks", Database.listChannelRanks(this.name)); + user.socket.emit("channelRanks", this.server.db.listChannelRanks(this.name)); } } @@ -777,8 +774,7 @@ Channel.prototype.sendRecentChat = function(user) { /* REGION Broadcasts to all clients */ Channel.prototype.sendAll = function(message, data) { - io.sockets.in(this.name).emit(message, data); - NWS.inRoom(this.name).emit(message, data); + this.server.io.sockets.in(this.name).emit(message, data); } Channel.prototype.sendAllWithPermission = function(perm, msg, data) { @@ -811,7 +807,7 @@ Channel.prototype.broadcastUsercount = function() { } Channel.prototype.broadcastNewUser = function(user) { - var aliases = Database.getAliases(user.ip); + var aliases = this.server.db.getAliases(user.ip); var chan = this; this.ip_alias[user.ip] = aliases; aliases.forEach(function(alias) { @@ -939,7 +935,7 @@ Channel.prototype.broadcastBanlist = function() { } Channel.prototype.broadcastRankTable = function() { - var ranks = Database.listChannelRanks(this.name); + var ranks = this.server.db.listChannelRanks(this.name); for(var i = 0; i < this.users.length; i++) { this.sendACL(this.users[i]); } @@ -1299,7 +1295,7 @@ Channel.prototype.tryQueuePlaylist = function(user, data) { return; } - var pl = Database.loadUserPlaylist(user.name, data.name); + var pl = this.server.db.loadUserPlaylist(user.name, data.name); data.list = pl; data.queueby = user.name; this.addMediaList(data, user); @@ -1362,7 +1358,7 @@ Channel.prototype.tryUncache = function(user, data) { if(typeof data.id != "string") { return; } - if(Database.removeFromLibrary(this.name, data.id)) { + if(this.server.db.removeFromLibrary(this.name, data.id)) { delete this.library[data.id]; } } @@ -1866,7 +1862,7 @@ Channel.prototype.trySetRank = function(user, data) { var rrank = this.getRank(data.user); if(rrank >= user.rank) return; - Database.setChannelRank(this.name, data.user, data.rank); + this.server.db.setChannelRank(this.name, data.user, data.rank); } this.sendAllWithPermission("acl", "setChannelRank", data); @@ -1903,7 +1899,7 @@ Channel.prototype.tryPromoteUser = function(actor, data) { this.broadcastUserUpdate(receiver); } else { - Database.setChannelRank(this.name, data.name, rank); + this.server.db.setChannelRank(this.name, data.name, rank); } this.logger.log("*** " + actor.name + " promoted " + data.name + " from " + (rank - 1) + " to " + rank); //this.broadcastRankTable(); @@ -1940,7 +1936,7 @@ Channel.prototype.tryDemoteUser = function(actor, data) { this.broadcastUserUpdate(receiver); } else { - Database.setChannelRank(this.name, data.name, rank); + this.server.db.setChannelRank(this.name, data.name, rank); } this.logger.log("*** " + actor.name + " demoted " + data.name + " from " + (rank + 1) + " to " + rank); //this.broadcastRankTable(); @@ -1995,4 +1991,4 @@ Channel.prototype.tryChangeLeader = function(user, data) { this.changeLeader(data.name); } -exports.Channel = Channel; +module.exports = Channel; diff --git a/server.js b/server.js index 139c8c3e..1ae66fca 100644 --- a/server.js +++ b/server.js @@ -68,6 +68,7 @@ var Server = { ioserv: null, db: null, ips: {}, + acp: null, init: function () { this.app = express(); // channel path @@ -137,12 +138,15 @@ var Server = { // finally a valid user Logger.syslog.log("Accepted socket from /" + socket._ip); new User(socket, this); - }); + }.bind(this)); // init database this.db = require("./database"); this.db.setup(Config); this.db.init(); + + // init ACP + this.acp = require("./acp")(this); }, shutdown: function () { Logger.syslog.log("Unloading channels"); @@ -165,5 +169,5 @@ if(!Config.DEBUG) { }); process.on("exit", Server.shutdown); - process.on("SIGINT", Server.shutdown); + process.on("SIGINT", function () { process.exit(0); }); } diff --git a/user.js b/user.js index 4a261511..3b319022 100644 --- a/user.js +++ b/user.js @@ -13,16 +13,14 @@ var Rank = require("./rank.js"); var Auth = require("./auth.js"); var Channel = require("./channel.js").Channel; var formatTime = require("./media.js").formatTime; -var Server = require("./server.js"); -var Database = require("./database.js"); var Logger = require("./logger.js"); var Config = require("./config.js"); -var ACP = require("./acp"); var ActionLog = require("./actionlog"); // Represents a client connected via socket.io -var User = function(socket, ip) { - this.ip = ip; +var User = function(socket, Server) { + this.ip = socket._ip; + this.server = Server; this.socket = socket; this.loggedIn = false; this.rank = Rank.Anonymous; @@ -92,12 +90,12 @@ User.prototype.initCallbacks = function() { return; if(typeof data.name != "string") return; - if(!data.name.match(/^[a-zA-Z0-9-_]+$/)) + if(!data.name.match(/^[\w-_]+$/)) return; if(data.name.length > 100) return; data.name = data.name.toLowerCase(); - this.channel = Server.getOrCreateChannel(data.name); + this.channel = this.server.getChannel(data.name); if(this.loggedIn) { var chanrank = this.channel.getRank(this.name); if(chanrank > this.rank) { @@ -117,14 +115,6 @@ User.prototype.initCallbacks = function() { this.login(name, pw, session); }.bind(this)); - this.socket.on("register", function(data) { - if(data.name == undefined || data.pw == undefined) - return; - if(data.pw.length > 100) - data.pw = data.pw.substring(0, 100); - this.register(data.name, data.pw); - }.bind(this)); - this.socket.on("assignLeader", function(data) { if(this.channel != null) { this.channel.tryChangeLeader(this, data); @@ -328,18 +318,6 @@ User.prototype.initCallbacks = function() { } }.bind(this)); - this.socket.on("announce", function(data) { - if(Rank.hasPermission(this, "announce")) { - if(data.clear) { - Server.announcement = null; - } - else { - Server.io.sockets.emit("announcement", data); - Server.announcement = data; - } - } - }.bind(this)); - this.socket.on("setOptions", function(data) { if(this.channel != null) { this.channel.tryUpdateOptions(this, data); @@ -420,23 +398,6 @@ User.prototype.initCallbacks = function() { } }.bind(this)); - this.socket.on("setProfile", function(data) { - if(!this.name) { - return; - } - data.image = data.image || ""; - data.text = data.text || ""; - if(data.text.length > 4000) { - data.text = data.text.substring(0, 4000); - } - if(Database.setProfile(this.name, data)) { - this.profile = data; - if(this.channel != null) { - this.channel.broadcastUserUpdate(this); - } - } - }.bind(this)); - this.socket.on("listPlaylists", function(data) { if(this.name == "" || this.rank < 1) { this.socket.emit("listPlaylists", { @@ -446,7 +407,7 @@ User.prototype.initCallbacks = function() { return; } - var list = Database.getUserPlaylists(this.name); + var list = this.server.db.getUserPlaylists(this.name); for(var i = 0; i < list.length; i++) { list[i].time = formatTime(list[i].time); } @@ -477,12 +438,12 @@ User.prototype.initCallbacks = function() { } var pl = this.channel.playlist.items.toArray(); - var result = Database.saveUserPlaylist(pl, this.name, data.name); + var result = this.server.db.saveUserPlaylist(pl, this.name, data.name); this.socket.emit("savePlaylist", { success: result, error: result ? false : "Unknown" }); - var list = Database.getUserPlaylists(this.name); + var list = this.server.db.getUserPlaylists(this.name); for(var i = 0; i < list.length; i++) { list[i].time = formatTime(list[i].time); } @@ -502,8 +463,8 @@ User.prototype.initCallbacks = function() { return; } - Database.deleteUserPlaylist(this.name, data.name); - var list = Database.getUserPlaylists(this.name); + this.server.db.deleteUserPlaylist(this.name, data.name); + var list = this.server.db.getUserPlaylists(this.name); for(var i = 0; i < list.length; i++) { list[i].time = formatTime(list[i].time); } @@ -514,7 +475,7 @@ User.prototype.initCallbacks = function() { this.socket.on("acp-init", function() { if(this.global_rank >= Rank.Siteadmin) - ACP.init(this); + this.server.acp.init(this); }.bind(this)); this.socket.on("borrow-rank", function(rank) { @@ -580,7 +541,7 @@ User.prototype.login = function(name, pw, session) { lastguestlogin[this.ip] = Date.now(); this.rank = Rank.Guest; Logger.syslog.log(this.ip + " signed in as " + name); - Database.recordVisit(this.ip, name); + this.server.db.recordVisit(this.ip, name); this.name = name; this.loggedIn = false; this.socket.emit("login", { @@ -620,7 +581,7 @@ User.prototype.login = function(name, pw, session) { name: name }); Logger.syslog.log(this.ip + " logged in as " + name); - Database.recordVisit(this.ip, name); + this.server.db.recordVisit(this.ip, name); this.profile = { image: row.profile_image, text: row.profile_text @@ -695,4 +656,4 @@ User.prototype.register = function(name, pw) { } } -exports.User = User; +module.exports = User;