diff --git a/auth.js b/auth.js index 06a9520f..c096352c 100644 --- a/auth.js +++ b/auth.js @@ -109,3 +109,21 @@ exports.login = function(name, pw) { } return false; } + +exports.getGlobalRank = function(name) { + var db = mysql.createConnectionSync(); + db.connectSync(Config.MYSQL_SERVER, Config.MYSQL_USER, + Config.MYSQL_PASSWORD, Config.MYSQL_DB); + if(!db.connectedSync()) { + Logger.errlog.log("Auth.getGlobalRank: DB connection failed"); + return false; + } + var query = "SELECT * FROM registrations WHERE uname='{1}'" + .replace(/\{1\}/, name) + var results = db.querySync(query); + var rows = results.fetchAllSync(); + if(rows.length > 0) { + return rows[0].global_rank; + } + return 0; +} diff --git a/channel.js b/channel.js index cd9935ca..0036c228 100644 --- a/channel.js +++ b/channel.js @@ -18,6 +18,7 @@ var Logger = require("./logger.js"); var InfoGetter = require("./get-info.js"); var io = require("./server.js").io; var Rank = require("./rank.js"); +var Auth = require("./auth.js"); var ChatCommand = require("./chatcommand.js"); var Channel = function(name) { @@ -181,10 +182,12 @@ Channel.prototype.tryRegister = function(user) { } Channel.prototype.getRank = function(name) { + var global = Auth.getGlobalRank(name); if(!this.registered) { - return Rank.Guest; + return global; } - return Database.lookupChannelRank(this.name, name); + var local = Database.lookupChannelRank(this.name, name); + return local > global ? local : global; } Channel.prototype.saveRank = function(user) { @@ -385,6 +388,9 @@ Channel.prototype.sendRankStuff = function(user) { } user.socket.emit("chatFilters", {filters: filts}); } + if(Rank.hasPermission(user, "acl")) { + user.socket.emit("acl", Database.getChannelRanks(this.name)); + } } Channel.prototype.sendPlaylist = function(user) { @@ -445,6 +451,10 @@ Channel.prototype.broadcastNewUser = function(user) { meta: user.meta }); this.sendRankStuff(user); + if(user.rank > Rank.Guest) { + this.saveRank(user); + this.broadcastRankTable(); + } } Channel.prototype.broadcastRankUpdate = function(user) { @@ -491,6 +501,15 @@ Channel.prototype.broadcastBanlist = function() { } } +Channel.prototype.broadcastRankTable = function() { + var ranks = Database.getChannelRanks(this.name); + for(var i = 0; i < this.users.length; i++) { + if(Rank.hasPermission(this.users[i], "acl")) { + this.users[i].socket.emit("acl", ranks); + } + } +} + Channel.prototype.broadcastChatFilters = function() { var filts = new Array(this.filters.length); for(var i = 0; i < this.filters.length; i++) { @@ -1079,15 +1098,25 @@ Channel.prototype.tryPromoteUser = function(actor, data) { } } - if(receiver) { - if(actor.rank > receiver.rank + 1) { + var rank = receiver ? receiver.rank : this.getRank(data.name); + + if(actor.rank > rank + 1) { + rank++; + if(receiver) { receiver.rank++; if(receiver.loggedIn) { this.saveRank(receiver); } - this.logger.log("*** " + actor.name + " promoted " + receiver.name + " from " + (receiver.rank - 1) + " to " + receiver.rank); this.broadcastRankUpdate(receiver); } + else { + Database.saveChannelRank(this.name, { + name: data.name, + rank: rank + }); + } + this.logger.log("*** " + actor.name + " promoted " + data.name + " from " + (rank - 1) + " to " + rank); + this.broadcastRankTable(); } } @@ -1109,15 +1138,25 @@ Channel.prototype.tryDemoteUser = function(actor, data) { } } - if(receiver) { - if(actor.rank > receiver.rank) { + var rank = receiver ? receiver.rank : this.getRank(data.name); + + if(actor.rank > rank) { + rank--; + if(receiver) { receiver.rank--; if(receiver.loggedIn) { this.saveRank(receiver); } - this.logger.log("*** " + actor.name + " demoted " + receiver.name + " from " + (receiver.rank + 1) + " to " + receiver.rank); this.broadcastRankUpdate(receiver); } + else { + Database.saveChannelRank(this.name, { + name: data.name, + rank: rank + }); + } + this.logger.log("*** " + actor.name + " demoted " + data.name + " from " + (rank + 1) + " to " + rank); + this.broadcastRankTable(); } } diff --git a/database.js b/database.js index 7929d12b..09f35b09 100644 --- a/database.js +++ b/database.js @@ -264,3 +264,23 @@ exports.removeChannelBan = function(channame, ip) { db.closeSync(); return results; } + +exports.getChannelRanks = function(channame) { + var db = exports.getConnection(); + if(!db) { + return false; + } + + var query = "SELECT * FROM chan_{}_ranks WHERE 1" + .replace("{}", channame); + + var results = db.querySync(query); + if(results) { + var rows = results.fetchAllSync(); + db.closeSync(); + return rows; + } + else { + return []; + } +} diff --git a/package.json b/package.json index 16d5f43b..241f3c43 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Calvin Montgomery", "name": "CyTube", "description": "Online media synchronizer and chat", - "version": "1.2.2", + "version": "1.2.3", "repository": { "url": "http://github.com/calzoneman/sync" }, diff --git a/rank.js b/rank.js index 63c4fd9f..7c7387e1 100644 --- a/rank.js +++ b/rank.js @@ -19,6 +19,7 @@ var permissions = { acp : exports.Siteadmin, announce : exports.Siteadmin, registerChannel : exports.Owner, + acl : exports.Owner, queue : exports.Moderator, assignLeader : exports.Moderator, kick : exports.Moderator, diff --git a/server.js b/server.js index d98b686e..d08d345b 100644 --- a/server.js +++ b/server.js @@ -9,7 +9,7 @@ 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. */ -const VERSION = "1.2.2"; +const VERSION = "1.2.3"; var fs = require("fs"); var Logger = require("./logger.js"); diff --git a/www/assets/js/callbacks.js b/www/assets/js/callbacks.js index 3cb36239..82646141 100644 --- a/www/assets/js/callbacks.js +++ b/www/assets/js/callbacks.js @@ -101,6 +101,8 @@ function initCallbacks() { updateBanlist(data.entries); }); + socket.on("acl", updateACL); + socket.on("voteskip", function(data) { if(data.count > 0) { $("#voteskip").text("Voteskip ("+data.count+"/"+data.need+")"); diff --git a/www/assets/js/client.js b/www/assets/js/client.js index ac9c3caf..75d893b8 100644 --- a/www/assets/js/client.js +++ b/www/assets/js/client.js @@ -382,41 +382,50 @@ $("#updatemotd").click(function() { }); $("#show_chancontrols").click(function() { - $("#show_banlist").parent().removeClass("active"); - $("#show_motdeditor").parent().removeClass("active"); - $("#show_filtereditor").parent().removeClass("active"); - $("#show_chancontrols").parent().addClass("active"); + $("#modnav li").each(function() { + $(this).removeClass("active"); + }); $(".modonly").hide(); + $("#show_chancontrols").parent().addClass("active"); $("#chancontrols").show(); }); $("#show_banlist").click(function() { - $("#show_chancontrols").parent().removeClass("active"); - $("#show_motdeditor").parent().removeClass("active"); - $("#show_filtereditor").parent().removeClass("active"); - $("#show_banlist").parent().addClass("active"); + $("#modnav li").each(function() { + $(this).removeClass("active"); + }); $(".modonly").hide(); + $("#show_banlist").parent().addClass("active"); $("#banlist").show(); }); $("#show_motdeditor").click(function() { - $("#show_chancontrols").parent().removeClass("active"); - $("#show_banlist").parent().removeClass("active"); - $("#show_filtereditor").parent().removeClass("active"); - $("#show_motdeditor").parent().addClass("active"); + $("#modnav li").each(function() { + $(this).removeClass("active"); + }); $(".modonly").hide(); + $("#show_motdeditor").parent().addClass("active"); $("#motdeditor").show(); }); $("#show_filtereditor").click(function() { - $("#show_chancontrols").parent().removeClass("active"); - $("#show_banlist").parent().removeClass("active"); - $("#show_motdeditor").parent().removeClass("active"); - $("#show_filtereditor").parent().addClass("active"); + $("#modnav li").each(function() { + $(this).removeClass("active"); + }); $(".modonly").hide(); + $("#show_filtereditor").parent().addClass("active"); $("#filtereditor").show(); }); +$("#show_acl").click(function() { + $("#modnav li").each(function() { + $(this).removeClass("active"); + }); + $(".modonly").hide(); + $("#show_acl").parent().addClass("active"); + $("#channelranks").show(); +}); + function searchLibrary() { socket.emit("searchLibrary", { query: $("#library_query").val() diff --git a/www/assets/js/functions.js b/www/assets/js/functions.js index 71231f1c..9f014b9b 100644 --- a/www/assets/js/functions.js +++ b/www/assets/js/functions.js @@ -672,6 +672,50 @@ function updateChatFilters(entries) { add.click(cback); } +function updateACL(entries) { + entries.sort(function(a, b) { + var x = a.name.toLowerCase(); + var y = b.name.toLowerCase(); + return y == x ? 0 : (x < y ? -1 : 1); + }); + var tbl = $("#channelranks table"); + if(tbl.children().length > 1) { + $(tbl.children()[1]).remove(); + } + for(var i = 0; i < entries.length; i++) { + var tr = $("