mirror of https://github.com/calzoneman/sync.git
Work on ACP
This commit is contained in:
parent
d0be588149
commit
1272425205
|
@ -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));
|
||||||
|
}
|
||||||
|
};
|
|
@ -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
|
* Handles a request for the socket.io information
|
||||||
*/
|
*/
|
||||||
|
@ -200,8 +168,7 @@ function handleSocketConfig(req, res) {
|
||||||
"',ALLOW_SSL="+Config.get("https.enabled")+";" +
|
"',ALLOW_SSL="+Config.get("https.enabled")+";" +
|
||||||
(Config.get("https.enabled") ?
|
(Config.get("https.enabled") ?
|
||||||
"if(location.protocol=='https:'||USEROPTS.secure_connection){" +
|
"if(location.protocol=='https:'||USEROPTS.secure_connection){" +
|
||||||
"IO_URL=WEB_URL=SSL_URL;}" : ""));
|
"IO_URL=WEB_URL=SSL_URL;}" : "")); }
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/**
|
/**
|
||||||
|
@ -220,9 +187,12 @@ module.exports = {
|
||||||
app.get("/r/:channel", handleChannel);
|
app.get("/r/:channel", handleChannel);
|
||||||
app.get("/", handleIndex);
|
app.get("/", handleIndex);
|
||||||
app.get("/sioconfig", handleSocketConfig);
|
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) {
|
app.all("*", function (req, res, next) {
|
||||||
if (isSuspicious(req)) {
|
if (isSuspicious(req)) {
|
||||||
|
console.log("isSuspicious");
|
||||||
logRequest(req, 403);
|
logRequest(req, 403);
|
||||||
res.status(403);
|
res.status(403);
|
||||||
if (req.header("user-agent").toLowerCase() === "zmeu") {
|
if (req.header("user-agent").toLowerCase() === "zmeu") {
|
||||||
|
@ -238,8 +208,6 @@ module.exports = {
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
app.use(express.static("www"));
|
app.use(express.static("www"));
|
||||||
require("./auth").init(app);
|
|
||||||
require("./account").init(app);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
logRequest: logRequest,
|
logRequest: logRequest,
|
||||||
|
|
|
@ -12,6 +12,10 @@ html(lang="en")
|
||||||
#nav-collapsible.collapse.navbar-collapse
|
#nav-collapsible.collapse.navbar-collapse
|
||||||
ul.nav.navbar-nav
|
ul.nav.navbar-nav
|
||||||
mixin navdefaultlinks("/acp")
|
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")
|
mixin navloginlogout("/acp")
|
||||||
section#mainpage
|
section#mainpage
|
||||||
.container
|
.container
|
||||||
|
@ -22,6 +26,7 @@ html(lang="en")
|
||||||
div.input-group-btn
|
div.input-group-btn
|
||||||
button#acp-syslog-btn.btn.btn-default Syslog
|
button#acp-syslog-btn.btn.btn-default Syslog
|
||||||
button#acp-errlog-btn.btn.btn-default Error log
|
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")
|
input#acp-chanlog-name.form-control(type="text", placeholder="Channel name")
|
||||||
pre#acp-log
|
pre#acp-log
|
||||||
#acp-announcements.col-md-12(style="display: none")
|
#acp-announcements.col-md-12(style="display: none")
|
||||||
|
@ -40,7 +45,7 @@ html(lang="en")
|
||||||
.form-group
|
.form-group
|
||||||
.col-sm-10.col-sm-offset-2
|
.col-sm-10.col-sm-offset-2
|
||||||
button#acp-announce-submit.btn.btn-primary Announce
|
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
|
h3 Global Bans
|
||||||
table.table.table-striped.table-bordered
|
table.table.table-striped.table-bordered
|
||||||
thead
|
thead
|
||||||
|
@ -62,5 +67,60 @@ html(lang="en")
|
||||||
.form-group
|
.form-group
|
||||||
.col-sm-9.col-sm-offset-3
|
.col-sm-9.col-sm-offset-3
|
||||||
button#acp-gban-submit.btn.btn-danger Add ban
|
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
|
include footer
|
||||||
mixin footer()
|
mixin footer()
|
||||||
|
script(src="/js/acp.js")
|
||||||
|
|
|
@ -7,4 +7,7 @@
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in New Issue