Start working on ACP
This commit is contained in:
parent
91b8a6cab6
commit
5ca419d3e3
|
@ -31,7 +31,7 @@ I'm using v0.8.20, please feel free to report which versions do/do not work
|
|||
5. Install your distribution's `libmysqlclient` package
|
||||
6. Install the libmysql node module: `npm install mysql-libmysqlclient`
|
||||
7. Edit `config.js` and input your database details and connection port
|
||||
8. Edit `www/assets/js/client.js` and change the value of `IO_URL` to `yourhostname:port` where `port` is the port defined in `config.js`
|
||||
8. Edit `www/assets/js/iourl.js` and change the value of `IO_URL` to `yourhostname:port` where `port` is the port defined in `config.js`
|
||||
|
||||
Running
|
||||
-------
|
||||
|
|
101
database.js
Normal file
101
database.js
Normal file
|
@ -0,0 +1,101 @@
|
|||
var mysql = require('mysql-libmysqlclient');
|
||||
var Config = require('./config.js');
|
||||
|
||||
var initialized = false;
|
||||
|
||||
exports.init = function() {
|
||||
if(initialized)
|
||||
return;
|
||||
|
||||
var db = mysql.createConnectionSync();
|
||||
db.connectSync(Config.MYSQL_SERVER, Config.MYSQL_USER,
|
||||
Config.MYSQL_PASSWORD, Config.MYSQL_DB);
|
||||
var query = "CREATE TABLE IF NOT EXISTS `channels` \
|
||||
(`id` INT NOT NULL, \
|
||||
`name` VARCHAR(255) NOT NULL, \
|
||||
PRIMARY KEY (`id`)) \
|
||||
ENGINE = MyISAM;";
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
console.log("Database initialization failed! Could not create channel table");
|
||||
return false;
|
||||
}
|
||||
|
||||
var query = "CREATE TABLE IF NOT EXISTS `registrations` \
|
||||
(`id` INT NOT NULL, \
|
||||
`uname` VARCHAR(20) NOT NULL, \
|
||||
`pw` VARCHAR(64) NOT NULL, \
|
||||
`global_rank` INT NOT NULL, \
|
||||
PRIMARY KEY (`id`)) \
|
||||
ENGINE = MyISAM;";
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
console.log("Database initialization failed! Could not create registration table");
|
||||
return false;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
exports.listChannels = function() {
|
||||
if(!initialized)
|
||||
return false;
|
||||
var db = mysql.createConnectionSync();
|
||||
db.connectSync(Config.MYSQL_SERVER, Config.MYSQL_USER,
|
||||
Config.MYSQL_PASSWORD, Config.MYSQL_DB);
|
||||
var query = "SELECT * FROM `channels`";
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
console.log("Database channel listing failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(results) {
|
||||
var rows = results.fetchAllSync();
|
||||
db.closeSync();
|
||||
return rows;
|
||||
}
|
||||
};
|
||||
|
||||
exports.listUsers = function() {
|
||||
if(!initialized)
|
||||
return false;
|
||||
var db = mysql.createConnectionSync();
|
||||
db.connectSync(Config.MYSQL_SERVER, Config.MYSQL_USER,
|
||||
Config.MYSQL_PASSWORD, Config.MYSQL_DB);
|
||||
var query = "SELECT * FROM `registrations`";
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
console.log("Database user listing failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(results) {
|
||||
var rows = results.fetchAllSync();
|
||||
db.closeSync();
|
||||
return rows;
|
||||
}
|
||||
};
|
||||
|
||||
exports.listChannelRanks = function(chan) {
|
||||
if(!initialized)
|
||||
return false;
|
||||
var db = mysql.createConnectionSync();
|
||||
db.connectSync(Config.MYSQL_SERVER, Config.MYSQL_USER,
|
||||
Config.MYSQL_PASSWORD, Config.MYSQL_DB);
|
||||
var query = "SELECT * FROM `chan_{}_ranks`"
|
||||
.replace(/\{\}/, chan);
|
||||
console.log(query);
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
console.log("Database channel listing failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(results) {
|
||||
var rows = results.fetchAllSync();
|
||||
db.closeSync();
|
||||
return rows;
|
||||
}
|
||||
};
|
1
rank.js
1
rank.js
|
@ -13,6 +13,7 @@ exports.Owner = 3;
|
|||
exports.Siteadmin = 255;
|
||||
|
||||
var permissions = {
|
||||
acp: exports.Siteadmin,
|
||||
queue: exports.Moderator,
|
||||
assignLeader: exports.Moderator,
|
||||
kick: exports.Moderator,
|
||||
|
|
|
@ -11,6 +11,8 @@ var Config = require('./config.js');
|
|||
var connect = require('connect');
|
||||
var app = connect.createServer(connect.static(__dirname+'/www')).listen(Config.IO_PORT);
|
||||
var io = require('socket.io').listen(app);
|
||||
var Database = require('./database.js');
|
||||
Database.init();
|
||||
|
||||
exports.channels = {};
|
||||
|
||||
|
|
58
user.js
58
user.js
|
@ -10,6 +10,7 @@ var Rank = require('./rank.js');
|
|||
var Auth = require('./auth.js');
|
||||
var Channel = require('./channel.js').Channel;
|
||||
var Server = require('./server.js');
|
||||
var Database = require('./database.js');
|
||||
|
||||
// Represents a client connected via socket.io
|
||||
var User = function(socket, ip) {
|
||||
|
@ -133,8 +134,65 @@ User.prototype.initCallbacks = function() {
|
|||
}
|
||||
}.bind(this));
|
||||
|
||||
this.socket.on('adm', function(data) {
|
||||
if(Rank.hasPermission(this, "acp")) {
|
||||
this.handleAdm(data);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
// Handle administration
|
||||
User.prototype.handleAdm = function(data) {
|
||||
if(data.cmd == "listloadedchannels") {
|
||||
var chans = [];
|
||||
for(var chan in Server.channels) {
|
||||
var users = [];
|
||||
for(var i = 0; i < Server.channels[chan].users.length; i++) {
|
||||
users.push(Server.channels[chan].users[i].name);
|
||||
}
|
||||
chans.push({
|
||||
chan: chan,
|
||||
users: users
|
||||
});
|
||||
}
|
||||
this.socket.emit('adm', {
|
||||
cmd: "listloadedchannels",
|
||||
chans: chans
|
||||
});
|
||||
}
|
||||
else if(data.cmd == "listchannels") {
|
||||
this.socket.emit('adm', {
|
||||
cmd: "listchannels",
|
||||
chans: Database.listChannels()
|
||||
});
|
||||
}
|
||||
else if(data.cmd == "listusers") {
|
||||
var users = [];
|
||||
var dbusers = Database.listUsers();
|
||||
if(!dbusers)
|
||||
return;
|
||||
for(var i = 0; i < dbusers.length; i++) {
|
||||
users[i] = {
|
||||
name: dbusers[i].uname,
|
||||
rank: dbusers[i].global_rank
|
||||
};
|
||||
}
|
||||
this.socket.emit('adm', {
|
||||
cmd: "listusers",
|
||||
users: users
|
||||
});
|
||||
}
|
||||
else if(data.cmd == "listchannelranks") {
|
||||
if(data.chan == undefined)
|
||||
return;
|
||||
this.socket.emit('adm', {
|
||||
cmd: "listchannelranks",
|
||||
ranks: Database.listChannelRanks(data.chan)
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Attempt to login
|
||||
User.prototype.login = function(name, sha256) {
|
||||
// No password => try guest login
|
||||
|
|
90
www/acp.html
Normal file
90
www/acp.html
Normal file
|
@ -0,0 +1,90 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Sync</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="Calvin 'calzoneman' Montgomery">
|
||||
|
||||
<link href="./assets/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="./assets/css/ytsync.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
|
||||
}
|
||||
</style>
|
||||
<link href="./assets/css/bootstrap-responsive.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="brand" href="#">Sync</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li class="active"><a href="index.html">Home</a></li>
|
||||
</ul>
|
||||
<div class="navbar-form pull-right" id="loginform">
|
||||
<input class="span2" id="username" type="text" placeholder="Username">
|
||||
<input class="span2" id="password" type="password" placeholder="Password">
|
||||
<button class="btn" id="login">Login</button>
|
||||
</div>
|
||||
<div class="navbar-form pull-right" id="logoutform" style="display: none;">
|
||||
<button class="btn" id="logout">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div id="loggedin" class="span6" style="display: none;">
|
||||
<h3 id="welcome"></h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="margin-top: 20px;">
|
||||
<div class="span6">
|
||||
<h3>Channel List</h3>
|
||||
<table id="chanlist" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>id</th>
|
||||
<th>Channel Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<h3 id="channelh3">Channel: </h3>
|
||||
<input type="text" placeholder="New Rank">
|
||||
<table id="chanranks" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>Rank</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="margin-top: 50px;">
|
||||
</div>
|
||||
</div> <!-- /container -->
|
||||
|
||||
<script src="./assets/js/jquery.js"></script>
|
||||
<script src="./assets/js/webtoolkit.sha256.js" type="text/javascript"></script>
|
||||
<script src="./socket.io/socket.io.js"></script>
|
||||
<script src="./assets/js/iourl.js"></script>
|
||||
<script src="./assets/js/acp.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
183
www/assets/js/acp.js
Normal file
183
www/assets/js/acp.js
Normal file
|
@ -0,0 +1,183 @@
|
|||
/**
|
||||
* Copyright 2013 Calvin 'calzoneman' Montgomery
|
||||
*
|
||||
* Licensed under Creative Commons Attribution-NonCommercial 3.0
|
||||
* See http://creativecommons.org/licenses/by-nc/3.0/
|
||||
*
|
||||
*/
|
||||
|
||||
var RANK = 0;
|
||||
var uname = readCookie('sync_uname');
|
||||
var pw = readCookie('sync_pw');
|
||||
var manageChannel = false;
|
||||
|
||||
var Rank = {
|
||||
Guest: 0,
|
||||
Member: 1,
|
||||
Moderator: 2,
|
||||
Owner: 3,
|
||||
Siteadmin: 255
|
||||
};
|
||||
|
||||
var socket = io.connect(IO_URL);
|
||||
initCallbacks();
|
||||
|
||||
function initCallbacks() {
|
||||
|
||||
socket.on('adm', function(data) {
|
||||
console.log(data);
|
||||
if(data.cmd == "listchannels")
|
||||
handleChannelList(data);
|
||||
if(data.cmd == "listchannelranks")
|
||||
handleChannelRanks(data);
|
||||
});
|
||||
|
||||
socket.on('login', function(data) {
|
||||
if(data.success && $('#password').val()) {
|
||||
createCookie('sync_uname', uname, 1);
|
||||
createCookie('sync_pw', pw, 1);
|
||||
}
|
||||
if(data.success) {
|
||||
$('#loggedin').css('display', '');
|
||||
$('#logoutform').css('display', '');
|
||||
$('#loginform').css('display', 'none');
|
||||
}
|
||||
socket.emit('adm', {
|
||||
cmd: "listloadedchannels"
|
||||
});
|
||||
socket.emit('adm', {
|
||||
cmd: "listchannels"
|
||||
});
|
||||
socket.emit('adm', {
|
||||
cmd: "listusers"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleChannelList(data) {
|
||||
if($('#chanlist').children.length > 1)
|
||||
$($('#chanlist').children()[1]).remove();
|
||||
for(var i = 0; i < data.chans.length; i++) {
|
||||
var row = $('<tr/>').appendTo($('#chanlist'));
|
||||
var id = $('<td/>').appendTo(row).text(data.chans[i].id);
|
||||
var name = $('<td/>').appendTo(row).text(data.chans[i].name);
|
||||
var manage = $('<button/>').addClass("btn pull-right").appendTo(name)
|
||||
.text('Manage Ranks');
|
||||
var cname = data.chans[i].name;
|
||||
manage.click(function() {
|
||||
manageChannelRanks(this);
|
||||
}.bind(cname));
|
||||
}
|
||||
}
|
||||
|
||||
function manageChannelRanks(name) {
|
||||
manageChannel = name;
|
||||
$('#channelh3').text('Channel: ' + name);
|
||||
socket.emit('adm', {
|
||||
cmd: "listchannelranks",
|
||||
chan: name
|
||||
});
|
||||
}
|
||||
|
||||
function handleChannelRanks(data) {
|
||||
if($('#chanranks').children.length > 1)
|
||||
$($('#chanranks').children()[1]).remove();
|
||||
for(var i = 0; i < data.ranks.length; i++) {
|
||||
var row = $('<tr/>').appendTo($('#chanranks'));
|
||||
var id = $('<td/>').appendTo(row).text(data.ranks[i].name);
|
||||
var rank = $('<td/>').appendTo(row);
|
||||
var rtxt = $('<span/>').appendTo(rank).text(data.ranks[i].rank);
|
||||
var edit = $('<button/>').addClass("btn pull-right").appendTo(rank)
|
||||
.text('Edit');
|
||||
|
||||
edit.click(function() {
|
||||
var txt = rtxt.text();
|
||||
rtxt.text('');
|
||||
var textbox = $('<input/>').attr('type', 'text').attr('value', txt)
|
||||
.insertBefore(edit, rank);
|
||||
textbox.focus();
|
||||
textbox.blur(function() {
|
||||
rtxt.text(textbox.val());
|
||||
socket.emit('adm', {
|
||||
cmd: "updatechanrank",
|
||||
chan: manageChannel,
|
||||
user: id.text(),
|
||||
rank: parseInt(textbox.val())
|
||||
});
|
||||
textbox.remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var params = {};
|
||||
if(window.location.search) {
|
||||
var parameters = window.location.search.substring(1).split('&');
|
||||
for(var i = 0; i < parameters.length; i++) {
|
||||
var s = parameters[i].split('=');
|
||||
if(s.length != 2)
|
||||
continue;
|
||||
params[s[0]] = s[1];
|
||||
}
|
||||
}
|
||||
|
||||
if(uname != null && pw != null && pw != "false") {
|
||||
socket.emit('login', {
|
||||
name: uname,
|
||||
sha256: pw
|
||||
});
|
||||
}
|
||||
|
||||
function loginClick() {
|
||||
uname = $('#username').val();
|
||||
if($('#password').val() == "")
|
||||
pw = "";
|
||||
else
|
||||
pw = SHA256($('#password').val());
|
||||
socket.emit('login', {
|
||||
name: uname,
|
||||
sha256: pw
|
||||
});
|
||||
};
|
||||
|
||||
$('#login').click(loginClick);
|
||||
$('#username').keydown(function(ev) {
|
||||
if(ev.key == 13)
|
||||
loginClick();
|
||||
});
|
||||
$('#password').keydown(function(ev) {
|
||||
if(ev.key == 13)
|
||||
loginClick();
|
||||
});
|
||||
|
||||
$('#logout').click(function() {
|
||||
eraseCookie('sync_uname');
|
||||
eraseCookie('sync_pw');
|
||||
document.location.reload(true);
|
||||
});
|
||||
|
||||
|
||||
function createCookie(name,value,days) {
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||||
var expires = "; expires="+date.toGMTString();
|
||||
}
|
||||
else var expires = "";
|
||||
document.cookie = name+"="+value+expires+"; path=/";
|
||||
}
|
||||
|
||||
function readCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function eraseCookie(name) {
|
||||
createCookie(name,"",-1);
|
||||
}
|
|
@ -6,7 +6,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
const IO_URL = "http://somewebsite:1337";
|
||||
const SYNC_THRESHOLD = 2;
|
||||
var LEADER = false;
|
||||
var PLAYER = false;
|
||||
|
|
9
www/assets/js/iourl.js
Normal file
9
www/assets/js/iourl.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* Copyright 2013 Calvin 'calzoneman' Montgomery
|
||||
*
|
||||
* Licensed under Creative Commons Attribution-NonCommercial 3.0
|
||||
* See http://creativecommons.org/licenses/by-nc/3.0/
|
||||
*
|
||||
*/
|
||||
|
||||
const IO_URL = "http://localhost:1337";
|
|
@ -94,6 +94,7 @@
|
|||
<script src="./socket.io/socket.io.js"></script>
|
||||
<script src="./assets/js/functions.js"></script>
|
||||
<script src="./assets/js/callbacks.js"></script>
|
||||
<script src="./assets/js/iourl.js"></script>
|
||||
<script src="./assets/js/client.js"></script>
|
||||
<script src="./assets/js/swf.js"></script>
|
||||
|
||||
|
|
Loading…
Reference in a new issue