I think it works

This commit is contained in:
Calvin Montgomery 2013-07-15 23:01:12 -04:00
parent bf8fef29cf
commit 5a9b3128d1
4 changed files with 189 additions and 228 deletions

284
acp.js
View file

@ -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);
});
}
}
}

View file

@ -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;

View file

@ -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); });
}

67
user.js
View file

@ -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;