Work on ACP

This commit is contained in:
calzoneman 2014-01-28 20:04:25 -06:00
parent d0be588149
commit 1272425205
5 changed files with 238 additions and 38 deletions

112
lib/web/acp.js Normal file
View file

@ -0,0 +1,112 @@
var path = require("path");
var fs = require("fs");
var webserver = require("./webserver");
var sendJade = require("./jade").sendJade;
var Logger = require("../logger");
var db = require("../database");
function checkAdmin(cb) {
return function (req, res) {
webserver.logRequest(req);
var auth = req.cookies.auth;
if (!auth) {
res.send(403);
return;
}
db.users.verifyAuth(auth, function (err, user) {
if (err) {
if (err === "Invalid auth string" ||
err === "Auth string does not match an existing user") {
res.send(403);
} else {
res.send(500);
}
return;
}
if (user.global_rank < 255) {
res.send(403);
Logger.eventlog.log("[acp] Attempted GET /acp from non-admin " +
user.name + "@" + webserver.ipForRequest(req));
return;
}
cb(req, res, user);
});
};
}
/**
* Handles a request for the ACP
*/
function handleAcp(req, res, user) {
sendJade(res, "acp", {
loginName: user.name,
loggedIn: true
});
}
/**
* Streams the last length bytes of file to the given HTTP response
*/
function readLog(res, file, length) {
fs.stat(file, function (err, data) {
if (err) {
res.send(500);
return;
}
var start = Math.max(0, data.size - length);
if (isNaN(start)) {
res.send(500);
}
var end = Math.max(0, data.size - 1);
if (isNaN(end)) {
res.send(500);
}
fs.createReadStream(file, { start: start, end: end })
.pipe(res);
});
}
/**
* Handles a request to read the syslog
*/
function handleReadSyslog(req, res) {
readLog(res, path.join(__dirname, "..", "..", "sys.log"), 1048576);
}
/**
* Handles a request to read the error log
*/
function handleReadErrlog(req, res) {
readLog(res, path.join(__dirname, "..", "..", "error.log"), 1048576);
}
/**
* Handles a request to read the http log
*/
function handleReadHttplog(req, res) {
readLog(res, path.join(__dirname, "..", "..", "http.log"), 1048576);
}
/**
* Handles a request to read a channel log
*/
function handleReadChanlog(req, res) {
if (!req.params.name.match(/^[\w-]{1,30}$/)) {
res.send(400);
return;
}
readLog(res, path.join(__dirname, "..", "..", "chanlogs", req.params.name + ".log"), 1048576);
}
module.exports = {
init: function (app) {
app.get("/acp", checkAdmin(handleAcp));
app.get("/acp/syslog", checkAdmin(handleReadSyslog));
app.get("/acp/errlog", checkAdmin(handleReadErrlog));
app.get("/acp/httplog", checkAdmin(handleReadHttplog));
app.get("/acp/chanlog/:name", checkAdmin(handleReadChanlog));
}
};

View file

@ -153,38 +153,6 @@ function handleIndex(req, res) {
});
}
/**
* Handles a request for the ACP
*/
function handleAcp(req, res) {
logRequest(req);
var auth = req.cookies.auth || "";
db.users.verifyAuth(auth, function (err, user) {
if (err) {
if (err === "Invalid auth string" ||
err === "Auth string does not match an existing user") {
res.send(403);
} else {
res.send(500);
}
return;
}
if (user.global_rank < 255) {
res.send(403);
Logger.eventlog.log("[acp] Attempted GET /acp from non-admin " + user.name +
"@" + ipForRequest(req));
return;
}
sendJade(res, "acp", {
loginName: user.name,
loggedIn: true
});
});
}
/**
* Handles a request for the socket.io information
*/
@ -200,8 +168,7 @@ function handleSocketConfig(req, res) {
"',ALLOW_SSL="+Config.get("https.enabled")+";" +
(Config.get("https.enabled") ?
"if(location.protocol=='https:'||USEROPTS.secure_connection){" +
"IO_URL=WEB_URL=SSL_URL;}" : ""));
}
"IO_URL=WEB_URL=SSL_URL;}" : "")); }
module.exports = {
/**
@ -220,9 +187,12 @@ module.exports = {
app.get("/r/:channel", handleChannel);
app.get("/", handleIndex);
app.get("/sioconfig", handleSocketConfig);
app.get("/acp", handleAcp);
require("./auth").init(app);
require("./account").init(app);
require("./acp").init(app);
app.all("*", function (req, res, next) {
if (isSuspicious(req)) {
console.log("isSuspicious");
logRequest(req, 403);
res.status(403);
if (req.header("user-agent").toLowerCase() === "zmeu") {
@ -238,8 +208,6 @@ module.exports = {
next();
});
app.use(express.static("www"));
require("./auth").init(app);
require("./account").init(app);
},
logRequest: logRequest,

View file

@ -12,6 +12,10 @@ html(lang="en")
#nav-collapsible.collapse.navbar-collapse
ul.nav.navbar-nav
mixin navdefaultlinks("/acp")
li#nav-acp-section.dropdown
a#nav-acp-dd-toggle.dropdown-toggle(data-toggle="dropdown", href="javascript:void(0)") Menu
span.caret
ul.dropdown-menu
mixin navloginlogout("/acp")
section#mainpage
.container
@ -22,6 +26,7 @@ html(lang="en")
div.input-group-btn
button#acp-syslog-btn.btn.btn-default Syslog
button#acp-errlog-btn.btn.btn-default Error log
button#acp-httplog-btn.btn.btn-default HTTP log
input#acp-chanlog-name.form-control(type="text", placeholder="Channel name")
pre#acp-log
#acp-announcements.col-md-12(style="display: none")
@ -40,7 +45,7 @@ html(lang="en")
.form-group
.col-sm-10.col-sm-offset-2
button#acp-announce-submit.btn.btn-primary Announce
#acp-global-bans.col-md-12
#acp-global-bans.col-md-12(style="display: none")
h3 Global Bans
table.table.table-striped.table-bordered
thead
@ -62,5 +67,60 @@ html(lang="en")
.form-group
.col-sm-9.col-sm-offset-3
button#acp-gban-submit.btn.btn-danger Add ban
#acp-user-lookup.col-md-12(style="display: none")
h3 Users
.input-group(style="max-width: 25%")
input#acp-ulookup-name.form-control(type="text")
span.input-group-btn
button#acp-ulookup-btn.btn.btn-default Search
table.table.table-bordered.table-striped(style="margin-top: 20px")
thead
tr
th#acp-ulookup-id ID
th#acp-ulookup-name Name
th#acp-ulookup-rank Rank
th#acp-ulookup-email Email
#acp-channel-lookup.col-md-12(style="display: none")
h3 Channels
form.form-inline(action="javascript:void(0)", role="form")
.form-group
input#acp-clookup-value.form-control(type="text", placeholder="Name")
.form-group
select#acp-clookup-field.form-control
option(value="name") Channel Name
option(value="owner") Channel Owner
button#acp-clookup-submit.btn.btn-default Search
table.table.table-bordered.table-striped(style="margin-top: 20px")
thead
tr
th ID
th Name
th Owner
#acp-loaded-channels.col-md-12(style="display: none")
h3 Loaded Channels
button#acp-lchannels-refresh.btn.btn-default Refresh
table.table.table-bordered.table-striped(style="margin-top: 20px")
thead
tr
th Title
th Usercount
th Now Playing
th Registered
th Public
th Force Unload
#acp-eventlog.col-md-12(style="display: none")
h3 Event Log
strong Filter event types
select#acp-eventlog-filter.form-control(multiple="multiple", style="max-width: 25%")
pre#acp-eventlog-text(style="margin-top: 20px")
#acp-stats.col-md-12(style="display: none")
h3 User Count
canvas#stat_users(width="100%", height="400")
h3 Channel Count
canvas#stat_channels(width="100%", height="400")
h3 Memory Usage
canvas#stat_mem(width="100%", height="400")
include footer
mixin footer()
script(src="/js/acp.js")

View file

@ -7,4 +7,7 @@
border-top-left-radius: 0;
border-top-right-radius: 0;
border-top: none;
max-height: 500px;
overflow-y: scroll;
overflow-x: hidden;
}

57
www/js/acp.js Normal file
View file

@ -0,0 +1,57 @@
function addMenuItem(target, text) {
var ul = $("#nav-acp-section ul");
var li = $("<li/>").appendTo(ul);
var a = $("<a/>").attr("href", "javascript:void(0)")
.text(text)
.appendTo(li)
.click(function () {
$(".col-md-12").hide();
$(target).show();
});
};
addMenuItem("#acp-logview", "Log Viewer");
addMenuItem("#acp-announcements", "Announcements");
addMenuItem("#acp-global-bans", "Global Bans");
addMenuItem("#acp-user-lookup", "Users");
addMenuItem("#acp-channel-lookup", "Channels");
addMenuItem("#acp-loaded-channels", "Active Channels");
addMenuItem("#acp-eventlog", "Event Log");
addMenuItem("#acp-stats", "Stats");
function readSyslog() {
$.ajax(location.protocol + "//" + location.host + "/acp/syslog").done(function (data) {
$("#acp-log").text(data);
$("#acp-log").scrollTop($("#acp-log").prop("scrollHeight"));
});
}
function readErrlog() {
$.ajax(location.protocol + "//" + location.host + "/acp/errlog").done(function (data) {
$("#acp-log").text(data);
$("#acp-log").scrollTop($("#acp-log").prop("scrollHeight"));
});
}
function readHttplog() {
$.ajax(location.protocol + "//" + location.host + "/acp/httplog").done(function (data) {
$("#acp-log").text(data);
$("#acp-log").scrollTop($("#acp-log").prop("scrollHeight"));
});
}
function readChanlog(name) {
$.ajax(location.protocol + "//" + location.host + "/acp/chanlog/" + name).done(function (data) {
$("#acp-log").text(data);
$("#acp-log").scrollTop($("#acp-log").prop("scrollHeight"));
});
}
$("#acp-syslog-btn").click(readSyslog);
$("#acp-errlog-btn").click(readErrlog);
$("#acp-httplog-btn").click(readHttplog);
$("#acp-chanlog-name").keyup(function (ev) {
if (ev.keyCode === 13) {
readChanlog($("#acp-chanlog-name").val());
}
});