diff --git a/lib/web/webserver.js b/lib/web/webserver.js index 60674998..d4fc4644 100644 --- a/lib/web/webserver.js +++ b/lib/web/webserver.js @@ -7,6 +7,7 @@ var Server = require("../server"); var $util = require("../utilities"); var Logger = require("../logger"); var Config = require("../config"); +var db = require("../database"); var httplog = new Logger.Logger(path.join(__dirname, "..", "..", "http.log")); @@ -152,6 +153,38 @@ 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 */ @@ -187,6 +220,7 @@ module.exports = { app.get("/r/:channel", handleChannel); app.get("/", handleIndex); app.get("/sioconfig", handleSocketConfig); + app.get("/acp", handleAcp); app.all("*", function (req, res, next) { if (isSuspicious(req)) { logRequest(req, 403); diff --git a/templates/acp.jade b/templates/acp.jade new file mode 100644 index 00000000..a9f84f3b --- /dev/null +++ b/templates/acp.jade @@ -0,0 +1,66 @@ +doctype html +html(lang="en") + head + include head + mixin head() + link(rel="stylesheet", type="text/css", href="/css/acp.css") + body + #wrap + nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation") + include nav + mixin navheader() + #nav-collapsible.collapse.navbar-collapse + ul.nav.navbar-nav + mixin navdefaultlinks("/acp") + mixin navloginlogout("/acp") + section#mainpage + .container + .row + #acp-logview.col-md-12(style="display: none") + h3 Log Viewer + .input-group + div.input-group-btn + button#acp-syslog-btn.btn.btn-default Syslog + button#acp-errlog-btn.btn.btn-default Error log + input#acp-chanlog-name.form-control(type="text", placeholder="Channel name") + pre#acp-log + #acp-announcements.col-md-12(style="display: none") + h3 Announcements + h3 New Announcement + .col-md-6 + form.form-horizontal(action="javascript:void(0)", role="form") + .form-group + label.control-label.col-sm-2(for="acp-announce-title") Title + .col-sm-10 + input#acp-announce-title.form-control(type="text") + .form-group + label.control-label.col-sm-2(for="acp-announce-content") Text + .col-sm-10 + textarea#acp-announce-content.form-control(type="text", rows="10") + .form-group + .col-sm-10.col-sm-offset-2 + button#acp-announce-submit.btn.btn-primary Announce + #acp-global-bans.col-md-12 + h3 Global Bans + table.table.table-striped.table-bordered + thead + tr + th + th IP Address + th Note + h3 New Global Ban + .col-md-6 + form.form-horizontal(action="javascript:void(0)", role="form") + .form-group + label.control-label.col-sm-3(for="acp-gban-ip") IP Address + .col-sm-9 + input#acp-gban-ip.form-control(type="text") + .form-group + label.control-label.col-sm-3(for="acp-gban-note") Note + .col-sm-9 + input#acp-gban-note.form-control(type="text") + .form-group + .col-sm-9.col-sm-offset-3 + button#acp-gban-submit.btn.btn-danger Add ban + include footer + mixin footer() diff --git a/www/css/acp.css b/www/css/acp.css new file mode 100644 index 00000000..271c5bd2 --- /dev/null +++ b/www/css/acp.css @@ -0,0 +1,10 @@ +#acp-logview .input-group-btn > button, #acp-logview .input-group > input { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +#acp-log { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-top: none; +}