mirror of https://github.com/calzoneman/sync.git
Add username bans, tweak ban interface
This commit is contained in:
parent
505c628eb9
commit
f8b0b06caf
194
channel.js
194
channel.js
|
@ -68,6 +68,7 @@ var Channel = function(name) {
|
|||
html: ""
|
||||
};
|
||||
this.ipbans = {};
|
||||
this.namebans = {};
|
||||
this.logins = {};
|
||||
this.logger = new Logger.Logger("chanlogs/" + this.name + ".log");
|
||||
this.i = 0;
|
||||
|
@ -80,6 +81,11 @@ var Channel = function(name) {
|
|||
this.css = "";
|
||||
this.js = "";
|
||||
|
||||
this.ipkey = "";
|
||||
for(var i = 0; i < 15; i++) {
|
||||
this.ipkey += "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[parseInt(Math.random() * 65)]
|
||||
}
|
||||
|
||||
Database.loadChannel(this);
|
||||
if(this.registered) {
|
||||
this.loadDump();
|
||||
|
@ -290,6 +296,102 @@ Channel.prototype.cacheMedia = function(media) {
|
|||
return false;
|
||||
}
|
||||
|
||||
Channel.prototype.banName = function(actor, name) {
|
||||
if(!Rank.hasPermission(actor, "ban")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = name.toLowerCase();
|
||||
|
||||
var rank = this.getRank(name);
|
||||
if(rank < 1) {
|
||||
actor.socket.emit("errorMsg", {msg: "You can't ban guest names. Use a kick or IP ban."});
|
||||
return false;
|
||||
}
|
||||
|
||||
if(rank >= actor.rank) {
|
||||
actor.socket.emit("errorMsg", {msg: "You don't have permission to ban this person."});
|
||||
return false;
|
||||
}
|
||||
|
||||
this.namebans[name] = actor.name;
|
||||
for(var i = 0; i < this.users.length; i++) {
|
||||
if(this.users[i].name.toLowerCase() == name) {
|
||||
this.kick(this.users[i], "You're banned!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.broadcastBanlist();
|
||||
this.logger.log(name + " was banned by " + actor.name);
|
||||
if(!this.registered) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Database.addChannelBan(this.name, actor, {
|
||||
ip: "*",
|
||||
name: name
|
||||
});
|
||||
}
|
||||
|
||||
Channel.prototype.unbanName = function(actor, name) {
|
||||
if(!Rank.hasPermission(actor, "ban")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.namebans[name] = null;
|
||||
delete this.namebans[name];
|
||||
this.broadcastBanlist();
|
||||
this.logger.log(name + " was unbanned by " + actor.name);
|
||||
|
||||
return Database.removeNameBan(this.name, name);
|
||||
}
|
||||
|
||||
Channel.prototype.tryIPBan = function(actor, data) {
|
||||
if(!Rank.hasPermission(actor, "ipban")) {
|
||||
return false;
|
||||
}
|
||||
if(typeof data.id != "string" || data.id.length != 15) {
|
||||
return false;
|
||||
}
|
||||
if(typeof data.name != "string") {
|
||||
return false;
|
||||
}
|
||||
var ip = this.hideIP(data.id);
|
||||
if(this.getIPRank(ip) >= actor.rank) {
|
||||
actor.socket.emit("errorMsg", {msg: "You don't have permission to ban this IP"});
|
||||
return false;
|
||||
}
|
||||
|
||||
if(data.range) {
|
||||
ip = ip.replace(/(\d+)\.(\d+)\.(\d+)\.(\d+)/, "$1.$2.$3");
|
||||
for(var ip2 in this.logins) {
|
||||
if(ip2.indexOf(ip) == 0 && this.getIPRank(ip2) >= actor.rank) {
|
||||
actor.socket.emit("errorMsg", {msg: "You don't have permission to ban this IP"});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.ipbans[ip] = [data.name, actor.name];
|
||||
this.broadcastBanlist();
|
||||
this.logger.log(ip + " (" + data.name + ") was banned by " + actor.name);
|
||||
|
||||
for(var i = 0; i < this.users.length; i++) {
|
||||
if(this.users[i].ip.indexOf(ip) == 0) {
|
||||
this.kick(this.users[i], "Your IP is banned!");
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if(!this.registered)
|
||||
return false;
|
||||
|
||||
// Update database ban table
|
||||
return Database.addChannelBan(this.name, actor, {
|
||||
ip: ip,
|
||||
name: data.name
|
||||
});
|
||||
}
|
||||
|
||||
Channel.prototype.banIP = function(actor, receiver) {
|
||||
if(!Rank.hasPermission(actor, "ipban"))
|
||||
return false;
|
||||
|
@ -315,6 +417,10 @@ Channel.prototype.unbanIP = function(actor, ip) {
|
|||
if(!Rank.hasPermission(actor, "ipban"))
|
||||
return false;
|
||||
|
||||
if(this.getIPRank(ip) >= actor.rank) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.ipbans[ip] = null;
|
||||
|
||||
if(!this.registered)
|
||||
|
@ -325,6 +431,16 @@ Channel.prototype.unbanIP = function(actor, ip) {
|
|||
return Database.removeChannelBan(this.name, ip);
|
||||
}
|
||||
|
||||
Channel.prototype.tryUnban = function(actor, data) {
|
||||
if(data.id) {
|
||||
var ip = this.hideIP(data.id);
|
||||
this.unbanIP(actor, ip);
|
||||
}
|
||||
else if(data.name) {
|
||||
this.unbanName(actor, data.name);
|
||||
}
|
||||
}
|
||||
|
||||
Channel.prototype.search = function(query, callback) {
|
||||
// Search youtube
|
||||
if(callback) {
|
||||
|
@ -369,6 +485,11 @@ Channel.prototype.userJoin = function(user) {
|
|||
this.kick(user, "You're banned!");
|
||||
return;
|
||||
}
|
||||
if(user.name && user.name.toLowerCase() in this.namebans &&
|
||||
this.namebans[user.name.toLowerCase()] != null) {
|
||||
this.kick(user, "You're banned!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Join the socket pool for this channel
|
||||
user.socket.join(this.name);
|
||||
|
@ -470,6 +591,21 @@ Channel.prototype.kick = function(user, reason) {
|
|||
user.socket.disconnect(true);
|
||||
}
|
||||
|
||||
Channel.prototype.hideIP = function(ip) {
|
||||
while(ip.length < 15) {
|
||||
ip += "X";
|
||||
}
|
||||
var chars = new Array(15);
|
||||
for(var i = 0; i < ip.length; i++) {
|
||||
chars[i] = String.fromCharCode(ip.charCodeAt(i) ^ this.ipkey.charCodeAt(i));
|
||||
if(chars[i] == "X") {
|
||||
chars[i] = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return chars.join("");
|
||||
}
|
||||
|
||||
Channel.prototype.sendRankStuff = function(user) {
|
||||
if(Rank.hasPermission(user, "ipban")) {
|
||||
var ents = [];
|
||||
|
@ -482,13 +618,28 @@ Channel.prototype.sendRankStuff = function(user) {
|
|||
else {
|
||||
name = this.ipbans[ip][0];
|
||||
}
|
||||
var id = this.hideIP(ip);
|
||||
var disp = ip;
|
||||
if(user.rank < Rank.Siteadmin) {
|
||||
disp = "(Hidden)";
|
||||
}
|
||||
ents.push({
|
||||
ip: ip,
|
||||
ip: disp,
|
||||
id: id,
|
||||
name: name,
|
||||
banner: this.ipbans[ip][1]
|
||||
});
|
||||
}
|
||||
}
|
||||
for(var name in this.namebans) {
|
||||
if(this.namebans[name] != null) {
|
||||
ents.push({
|
||||
ip: "*",
|
||||
name: name,
|
||||
banner: this.namebans[name]
|
||||
});
|
||||
}
|
||||
}
|
||||
user.socket.emit("banlist", {entries: ents});
|
||||
}
|
||||
if(Rank.hasPermission(user, "seenlogins")) {
|
||||
|
@ -496,11 +647,13 @@ Channel.prototype.sendRankStuff = function(user) {
|
|||
for(var ip in this.logins) {
|
||||
var disp = ip;
|
||||
if(user.rank < Rank.Siteadmin) {
|
||||
disp = "(Masked)";
|
||||
disp = "(Hidden)";
|
||||
}
|
||||
ents.push({
|
||||
ip: disp,
|
||||
name: this.logins[ip].join(",")
|
||||
id: this.hideIP(ip),
|
||||
names: this.logins[ip],
|
||||
banned: (ip in this.ipbans && this.ipbans[ip] != null)
|
||||
});
|
||||
}
|
||||
user.socket.emit("seenlogins", {entries: ents});
|
||||
|
@ -591,6 +744,11 @@ Channel.prototype.broadcastNewUser = function(user) {
|
|||
if(!this.seen(user.ip, user.name)) {
|
||||
this.logins[user.ip].push(user.name);
|
||||
}
|
||||
if(user.name.toLowerCase() in this.namebans &&
|
||||
this.namebans[user.name.toLowerCase()] != null) {
|
||||
this.kick(user, "You're banned!");
|
||||
return;
|
||||
}
|
||||
this.sendAll("addUser", {
|
||||
name: user.name,
|
||||
rank: user.rank,
|
||||
|
@ -633,6 +791,7 @@ Channel.prototype.broadcastOpts = function() {
|
|||
|
||||
Channel.prototype.broadcastBanlist = function() {
|
||||
var ents = [];
|
||||
var adminents = [];
|
||||
for(var ip in this.ipbans) {
|
||||
if(this.ipbans[ip] != null) {
|
||||
var name;
|
||||
|
@ -642,16 +801,43 @@ Channel.prototype.broadcastBanlist = function() {
|
|||
else {
|
||||
name = this.ipbans[ip][0];
|
||||
}
|
||||
var id = this.hideIP(ip);
|
||||
ents.push({
|
||||
ip: "(Hidden)",
|
||||
id: id,
|
||||
name: name,
|
||||
banner: this.ipbans[ip][1]
|
||||
});
|
||||
adminents.push({
|
||||
ip: ip,
|
||||
id: id,
|
||||
name: name,
|
||||
banner: this.ipbans[ip][1]
|
||||
});
|
||||
}
|
||||
}
|
||||
for(var name in this.namebans) {
|
||||
if(this.namebans[name] != null) {
|
||||
ents.push({
|
||||
ip: "*",
|
||||
name: name,
|
||||
banner: this.namebans[name]
|
||||
});
|
||||
adminents.push({
|
||||
ip: "*",
|
||||
name: name,
|
||||
banner: this.namebans[name]
|
||||
});
|
||||
}
|
||||
}
|
||||
for(var i = 0; i < this.users.length; i++) {
|
||||
if(Rank.hasPermission(this.users[i], "ipban")) {
|
||||
this.users[i].socket.emit("banlist", {entries: ents});
|
||||
if(this.users[i].rank >= Rank.Siteadmin) {
|
||||
this.users[i].socket.emit("banlist", {entries: adminents});
|
||||
}
|
||||
else {
|
||||
this.users[i].socket.emit("banlist", {entries: ents});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,9 +38,6 @@ function handle(chan, user, msg, data) {
|
|||
else if(msg.indexOf("/ban ") == 0) {
|
||||
handleBan(chan, user, msg.substring(5).split(" "));
|
||||
}
|
||||
else if(msg.indexOf("/ipban ") == 0) {
|
||||
handleIpban(chan, user, msg.substring(7).split(" "));
|
||||
}
|
||||
else if(msg.indexOf("/unban ") == 0) {
|
||||
handleUnban(chan, user, msg.substring(7).split(" "));
|
||||
}
|
||||
|
@ -89,45 +86,6 @@ function handleBan(chan, user, args) {
|
|||
chan.kick(kickee, "(banned) " + reason);
|
||||
chan.banIP(user, kickee);
|
||||
}
|
||||
else if(!kickee && chan.getRank(args[0]) < user.rank) {
|
||||
for(var ip in chan.logins) {
|
||||
if(chan.getIPRank(ip) >= user.rank) {
|
||||
return;
|
||||
}
|
||||
if(!chan.seen(ip, args[0])) {
|
||||
continue;
|
||||
}
|
||||
if(args.length >= 2 && args[1] == "range") {
|
||||
var parts = ip.split(".");
|
||||
ip = parts[0] + "." + parts[1] + "." + parts[2];
|
||||
}
|
||||
chan.logger.log("*** " + user.name + " banned " + ip);
|
||||
chan.banIP(user, {
|
||||
ip: ip,
|
||||
name: args[0]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleIpban(chan, user, args) {
|
||||
if(Rank.hasPermission(user, "ipban") && args.length > 0) {
|
||||
var name = "";
|
||||
for(var ip in chan.logins) {
|
||||
if(ip.indexOf(args[0]) == 0) {
|
||||
if(chan.getIPRank(ip) >= user.rank) {
|
||||
return;
|
||||
}
|
||||
var names = chan.logins[ip];
|
||||
name = names[names.length - 1];
|
||||
}
|
||||
}
|
||||
chan.logger.log("*** " + user.name + " banned " + args[0]);
|
||||
chan.banIP(user, {
|
||||
ip: args[0],
|
||||
name: name
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
21
database.js
21
database.js
|
@ -202,7 +202,13 @@ exports.loadChannel = function(chan) {
|
|||
}
|
||||
var rows = results.fetchAllSync();
|
||||
for(var i = 0; i < rows.length; i++) {
|
||||
chan.ipbans[rows[i].ip] = [rows[i].name, rows[i].banner];
|
||||
// Name ban
|
||||
if(rows[i].ip == "*") {
|
||||
chan.namebans[rows[i].name] = rows[i].banner;
|
||||
}
|
||||
else {
|
||||
chan.ipbans[rows[i].ip] = [rows[i].name, rows[i].banner];
|
||||
}
|
||||
}
|
||||
|
||||
chan.logger.log("*** Loaded channel from database");
|
||||
|
@ -388,6 +394,19 @@ exports.removeChannelBan = function(channame, ip) {
|
|||
return results;
|
||||
}
|
||||
|
||||
exports.removeNameBan = function(channame, name) {
|
||||
var db = exports.getConnection();
|
||||
if(!db) {
|
||||
return false;
|
||||
}
|
||||
var query = "DELETE FROM `chan_{1}_bans` WHERE `ip` = '*' AND `name`='{2}'"
|
||||
.replace("{1}", sqlEscape(channame))
|
||||
.replace("{2}", sqlEscape(name));
|
||||
results = db.querySync(query);
|
||||
db.closeSync();
|
||||
return results;
|
||||
}
|
||||
|
||||
exports.getChannelRanks = function(channame) {
|
||||
var db = exports.getConnection();
|
||||
if(!db) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"author": "Calvin Montgomery",
|
||||
"name": "CyTube",
|
||||
"description": "Online media synchronizer and chat",
|
||||
"version": "1.8.1",
|
||||
"version": "1.8.2",
|
||||
"repository": {
|
||||
"url": "http://github.com/calzoneman/sync"
|
||||
},
|
||||
|
|
1
rank.js
1
rank.js
|
@ -27,6 +27,7 @@ var permissions = {
|
|||
assignLeader : exports.Moderator,
|
||||
kick : exports.Moderator,
|
||||
ipban : exports.Moderator,
|
||||
ban : exports.Moderator,
|
||||
promote : exports.Moderator,
|
||||
qlock : exports.Moderator,
|
||||
poll : exports.Moderator,
|
||||
|
|
|
@ -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.8.1";
|
||||
const VERSION = "1.8.2";
|
||||
|
||||
var fs = require("fs");
|
||||
var Logger = require("./logger.js");
|
||||
|
|
18
user.js
18
user.js
|
@ -143,6 +143,24 @@ User.prototype.initCallbacks = function() {
|
|||
}
|
||||
}.bind(this));
|
||||
|
||||
this.socket.on("banName", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.banName(this, data.name || "");
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this.socket.on("banIP", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryIPBan(this, data);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this.socket.on("unban", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryUnban(this, data);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this.socket.on("chatMsg", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryChat(this, data);
|
||||
|
|
|
@ -26,6 +26,10 @@ Callbacks = {
|
|||
$("#messagebuffer").scrollTop($("#messagebuffer").prop("scrollHeight"));
|
||||
},
|
||||
|
||||
errorMsg: function(data) {
|
||||
alert(data.msg);
|
||||
},
|
||||
|
||||
announcement: function(data) {
|
||||
$("#announcerow").html("");
|
||||
$("#announcerow").css("display", "");
|
||||
|
@ -269,11 +273,12 @@ Callbacks = {
|
|||
var name = $("<td/>").text(entries[i].name).appendTo(tr);
|
||||
var banner = $("<td/>").text(entries[i].banner).appendTo(tr);
|
||||
|
||||
var callback = (function(ip) { return function() {
|
||||
socket.emit("chatMsg", {
|
||||
msg: "/unban " + ip
|
||||
var callback = (function(id, name) { return function() {
|
||||
socket.emit("unban", {
|
||||
id: id,
|
||||
name: name
|
||||
});
|
||||
} })(entries[i].ip);
|
||||
} })(entries[i].id, entries[i].name);
|
||||
remove.click(callback);
|
||||
}
|
||||
},
|
||||
|
@ -299,27 +304,69 @@ Callbacks = {
|
|||
for(var i = 0; i < entries.length; i++) {
|
||||
var tr = $("<tr/>").appendTo(tbl);
|
||||
var bantd = $("<td/>").appendTo(tr);
|
||||
var ban = $("<button/>").addClass("btn btn-mini btn-danger")
|
||||
.text("Ban")
|
||||
.appendTo(bantd);
|
||||
var banrange = $("<button/>").addClass("btn btn-mini btn-danger")
|
||||
.text("Ban Range")
|
||||
.appendTo(bantd);
|
||||
if(entries[i].banned) {
|
||||
bantd.text("Banned");
|
||||
tr.addClass("alert alert-error");
|
||||
}
|
||||
else {
|
||||
var ban = $("<button/>").addClass("btn btn-mini btn-danger")
|
||||
.text("Ban IP")
|
||||
.appendTo(bantd);
|
||||
var banrange = $("<button/>").addClass("btn btn-mini btn-danger")
|
||||
.text("Ban IP Range")
|
||||
.appendTo(bantd);
|
||||
var callback = (function(id, name) { return function() {
|
||||
console.log(id, name);
|
||||
socket.emit("banIP", {
|
||||
id: id,
|
||||
name: name,
|
||||
range: false
|
||||
});
|
||||
return false;
|
||||
} })(entries[i].id, entries[i].names[0]);
|
||||
ban.click(callback);
|
||||
var callback2 = (function(id, name) { return function() {
|
||||
console.log(id, name);
|
||||
socket.emit("banIP", {
|
||||
id: id,
|
||||
name: name,
|
||||
range: true
|
||||
});
|
||||
return false;
|
||||
} })(entries[i].id, entries[i].names[0]);
|
||||
banrange.click(callback2);
|
||||
}
|
||||
var ip = $("<td/>").text(entries[i].ip).appendTo(tr);
|
||||
var name = $("<td/>").text(entries[i].name).appendTo(tr);
|
||||
|
||||
var callback = (function(name) { return function() {
|
||||
socket.emit("chatMsg", {
|
||||
msg: "/ban " + name
|
||||
});
|
||||
} })(entries[i].name.split(",")[0]);
|
||||
ban.click(callback);
|
||||
var callback2 = (function(name) { return function() {
|
||||
socket.emit("chatMsg", {
|
||||
msg: "/ban " + name + " range"
|
||||
});
|
||||
} })(entries[i].name.split(",")[0]);
|
||||
banrange.click(callback2);
|
||||
var name = $("<td/>").text(entries[i].names).appendTo(tr);
|
||||
tr.data("names", entries[i].names);
|
||||
tr.data("banned", entries[i].banned);
|
||||
tr.click(function(ev) {
|
||||
tbl.find(".name-detail").remove();
|
||||
if(this.data("namesopen")) {
|
||||
this.data("namesopen", false);
|
||||
return;
|
||||
}
|
||||
var names = this.data("names") || [];
|
||||
for(var i = names.length-1; i >= 0; i--) {
|
||||
var detail = $("<tr/>").insertAfter(this);
|
||||
detail.addClass("name-detail");
|
||||
if(this.data("banned")) {
|
||||
detail.addClass("alert alert-error");
|
||||
}
|
||||
var buttontd = $("<td/>").appendTo(detail);
|
||||
$("<button/>").addClass("btn btn-mini btn-danger")
|
||||
.text("Ban Name")
|
||||
.appendTo(buttontd)
|
||||
.click(function() {
|
||||
socket.emit("banName", {
|
||||
name: this
|
||||
});
|
||||
}.bind(names[i]));
|
||||
$("<td/>").text("\"").appendTo(detail);
|
||||
$("<td/>").text(names[i]).appendTo(detail);
|
||||
}
|
||||
this.data("namesopen", true);
|
||||
}.bind(tr));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -132,6 +132,15 @@ function addUserDropdown(entry, name) {
|
|||
});
|
||||
});
|
||||
|
||||
var nameban = $("<li />").appendTo(ul);
|
||||
var a = $("<a />").attr("tabindex", "-1").attr("href", "javascript:void(0);").appendTo(nameban);
|
||||
a.text("Name Ban");
|
||||
a.click(function() {
|
||||
socket.emit("banName", {
|
||||
name: name
|
||||
});
|
||||
});
|
||||
|
||||
$("<li />").addClass("divider").appendTo(ul);
|
||||
|
||||
var promote = $("<li />").appendTo(ul);
|
||||
|
|
Loading…
Reference in New Issue