Re-did admin page to support new ban system

Sorry AdmiralCurtis but your fixes focussed a lot on the new logic and we couldn't really work with it. Sorry if we wasted your time
This commit is contained in:
Kyle Warwick-Mathieu
2015-05-04 02:31:37 -04:00
parent d1df37d22f
commit c4cda866bf

View File

@@ -1,21 +1,3 @@
# DWC Network Server Emulator
# Copyright (C) 2014 SMTDDR
# Copyright (C) 2014 kyle95wm
# Copyright (C) 2014 AdmiralCurtiss
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from twisted.web import server, resource
from twisted.internet import reactor
from twisted.internet.error import ReactorAlreadyRunning
@@ -26,7 +8,6 @@ import collections
import json
import time
import datetime
import os.path
import logging
import other.utils as utils
import gamespy
@@ -45,25 +26,19 @@ logger = utils.create_logger(logger_name, logger_filename, -1, logger_output_to_
#
# NOTE: Must use double-quotes or json module will fail
# NOTE2: Do not check the .json file into public git!
adminpageconf = None
admin_username = None
admin_password = None
if os.path.exists('adminpageconf.json'):
try:
adminpageconf = json.loads(file('adminpageconf.json').read().strip())
admin_username = str(adminpageconf['username'])
admin_password = str(adminpageconf['password'])
except Exception as e:
logger.log(logging.WARNING, "Couldn't read adminpageconf.json. Admin page will not be available.")
logger.log(logging.WARNING, str(e))
adminpageconf = None
admin_username = None
admin_password = None
else:
logger.log(logging.INFO, "adminpageconf.json not found. Admin page will not be available.")
try:
adminpageconf = file('adminpageconf.json').read().strip()
except Exception,e:
logger.log(logging.INFO,"ERROR reading adminpageconf.json: "+str(e))
logger.log(logging.INFO," *** WARN: adminpageconf.json could not be read. Creating one with default values")
adminpageconf = '{"username":"admin","password":"opensesame"}'
fd = open('adminpageconf.json','w')
fd.write(adminpageconf)
fd.close()
adminpageconf = json.loads(adminpageconf)
admin_username = str(adminpageconf['username'])
admin_password = str(adminpageconf['password'])
class AdminPage(resource.Resource):
isLeaf = True
@@ -71,29 +46,6 @@ class AdminPage(resource.Resource):
def __init__(self,adminpage):
self.adminpage = adminpage
def get_header(self, title = None):
if not title:
title = 'AltWfc Admin Page'
s = (
'<html>'
'<head>'
'<title>' + title + '</title>'
'</head>'
'<body>'
'<p>'
'<a href="/banhammer">Blacklist</a> '
'<a href="/whitelist">Whitelist</a> '
'</p>'
)
return s
def get_footer(self):
s = (
'</body>'
'</html>'
)
return s
def is_authorized(self, request):
is_auth = False
response_code = 401
@@ -103,8 +55,13 @@ class AdminPage(resource.Resource):
expected_auth = base64.encodestring(admin_username+":"+admin_password).strip()
actual_auth = request.getAllHeaders()['authorization'].replace("Basic ","").strip()
if actual_auth == expected_auth:
logger.log(logging.INFO,address+" Auth Success")
is_auth = True
if actual_auth == 'YWRtaW46b3BlbnNlc2FtZQ==':
error_message = ( 'You must change the default values in adminpageconf.json'
'<a href="http://%20:%20@'+request.getHeader('host')+'">[LOG OUT]</a>' )
response_code = 500
else:
logger.log(logging.INFO,address+" Auth Success")
is_auth = True
except Exception,e:
logger.log(logging.INFO,address+" Auth Error: "+str(e))
if not is_auth:
@@ -114,67 +71,59 @@ class AdminPage(resource.Resource):
request.write(error_message)
return is_auth
def update_whitelist(self, request):
def update_banlist(self, request):
address = request.getClientIP()
dbconn = sqlite3.connect('gpcm.db')
userid = request.args['userid'][0].strip()
gameid = request.args['gameid'][0].upper().strip()
macadr = request.args['macadr'][0].strip()
actiontype = request.args['actiontype'][0]
if not userid.isdigit() or not gameid.isalnum() or not macadr.isalnum():
ipaddr = request.args['ipaddr'][0].strip()
actiontype = request.args['action'][0]
if not gameid.isalnum():
request.setResponseCode(500)
logger.log(logging.INFO,address+" Bad data "+userid+" "+gameid+" "+macadr)
logger.log(logging.INFO,address+" Bad data "+gameid+" "+ipaddr)
return "Bad data"
if actiontype == 'add':
dbconn.cursor().execute('insert into whitelist values(?,?,?)',(userid,gameid,macadr))
responsedata = "Added macadr=%s for gameid=%s, userid=%s" % (macadr,gameid,userid)
if actiontype == 'ban':
dbconn.cursor().execute('insert into banned values(?,?)',(gameid[:-1],ipaddr))
responsedata = "Added gameid=%s, ipaddr=%s" % (gameid[:-1],ipaddr)
else:
dbconn.cursor().execute('delete from whitelist where userid=? and gameid=? and macadr=?',(userid,gameid,macadr))
responsedata = "Removed macadr=%s for gameid=%s, userid=%s" % (macadr,gameid,userid)
dbconn.cursor().execute('delete from banned where gameid=? and ipaddr=?',(gameid[:-1],ipaddr))
responsedata = "Removed gameid=%s, ipaddr=%s" % (gameid[:-1],ipaddr)
dbconn.commit()
dbconn.close()
logger.log(logging.INFO,address+" "+responsedata)
request.setHeader("Content-Type", "text/html; charset=utf-8")
request.setHeader("Location", "/whitelist")
request.setResponseCode(303)
return responsedata
def render_whitelist(self, request):
def render_banlist(self, request):
address = request.getClientIP()
dbconn = sqlite3.connect('gpcm.db')
logger.log(logging.INFO,address+" Viewed whitelist")
responsedata = (""
logger.log(logging.INFO,address+" Viewed banlist")
responsedata = ("<html><meta charset='utf-8'>\r\n"
"<title>altwfc admin page - banList</title>"
'<a href="http://%20:%20@'+request.getHeader('host')+'">[CLICK HERE TO LOG OUT]</a>'
"<form action='updatewhitelist' method='POST'>"
"userid:<input type='text' name='userid'>\r\n"
"gameid:<input type='text' name='gameid'>\r\n"
"macadr:<input type='text' name='macadr'>\r\n"
"<input type='hidden' name='actiontype' value='add'>\r\n"
"<input type='submit' value='Add to whitelist'></form>\r\n"
"<table border='1'>"
"<tr><td>userid</td><td>gameid</td><td>macadr</td></tr>\r\n")
for row in dbconn.cursor().execute("select * from whitelist"):
userid = str(row[0])
gameid = str(row[1])
macadr = str(row[2])
responsedata += ("<tr><td>"+userid+"</td><td>"+gameid+"</td><td>"+macadr+"</td>"
"<td><form action='updatewhitelist' method='POST'>"
"<input type='hidden' name='userid' value='"+userid+"'>"
"<tr><td>gameid</td><td>ipAddr</td></tr>\r\n")
for row in dbconn.cursor().execute("select * from banned"):
gameid = str(row[0])
ipaddr = str(row[1])
responsedata += ("<tr><td>"+gameid+"</td><td>"+ipaddr+"</td>"
"<td><form action='updatebanlist' method='POST'>"
"<input type='hidden' name='gameid' value='"+gameid+"'>"
"<input type='hidden' name='macadr' value='"+macadr+"'>"
"<input type='hidden' name='actiontype' value='remove'>\r\n"
"<input type='submit' value='Remove from whitelist'></form></td></tr>\r\n")
responsedata += "</table>"
"<input type='hidden' name='ipaddr' value='"+ipaddr+"'>"
"<input type='hidden' name='action' value='unban'>\r\n"
"<input type='submit' value='----- UNBAN -----'></form></td></tr>\r\n")
responsedata += "</table></html>"
dbconn.close()
request.setHeader("Content-Type", "text/html; charset=utf-8")
return responsedata
def render_not_available(self, request):
request.setResponseCode(403)
request.setHeader('WWW-Authenticate', 'Basic realm="ALTWFC"')
request.write('No admin credentials set. Admin page is not available.')
def render_blacklist(self, request):
def render_GET(self, request):
if not self.is_authorized(request):
return ""
if request.path == "/banlist":
return self.render_banlist(request)
if request.path != "/banhammer":
request.setResponseCode(500)
return "wrong url path"
sqlstatement = (''
'select users.profileid,enabled,data,users.gameid,console,users.userid '
'from nas_logins '
@@ -189,13 +138,18 @@ class AdminPage(resource.Resource):
'order by users.gameid '
'')
dbconn = sqlite3.connect('gpcm.db')
responsedata = (""
banned_list = []
for row in dbconn.cursor().execute("SELECT * FROM BANNED"):
banned_list.append(str(row[0])+":"+str(row[1]))
responsedata = ("<html><meta charset='utf-8'>\r\n"
"<title>altwfc admin page</title>"
'<a href="http://%20:%20@'+request.getHeader('host')+'">[CLICK HERE TO LOG OUT]</a>'
"<br><br>"
'<a href="http://'+request.getHeader('host')+'/banlist">BanList</a>'
"<table border='1'>"
"<tr><td>ingamesn or devname</td><td>gameid</td>"
"<td>Enabled</td><td>newest dwc_pid</td>"
"<td>gsbrcd</td><td>userid</td><td>IP</td></tr>\r\n")
"<td>gsbrcd</td><td>userid</td><td>ipAddr</td></tr>\r\n")
for row in dbconn.cursor().execute(sqlstatement):
dwc_pid = str(row[0])
enabled = str(row[1])
@@ -204,7 +158,7 @@ class AdminPage(resource.Resource):
is_console = int(str(row[4]))
userid = str(row[5])
gsbrcd = str(nasdata['gsbrcd'])
ipaddr = str (nasdata['ipaddr'])
ipaddr = str(nasdata['ipaddr'])
ingamesn = ''
if 'ingamesn' in nasdata:
ingamesn = str(nasdata['ingamesn'])
@@ -226,95 +180,35 @@ class AdminPage(resource.Resource):
responsedata += "<td>"+gsbrcd+"</td>"
responsedata += "<td>"+userid+"</td>"
responsedata += "<td>"+ipaddr+"</td>"
if enabled == "1":
responsedata += ("<td><form action='disableuser' method='POST'>"
"<input type='hidden' name='userid' value='"+userid+"'>"
if gameid[:-1]+":"+ipaddr in banned_list:
responsedata += ("<td><form action='updatebanlist' method='POST'>"
"<input type='hidden' name='gameid' value='"+gameid+"'>"
"<input type='hidden' name='ingamesn' value='"+ingamesn+"'>"
"<input type='hidden' name='ipaddr' value='"+ipaddr+"'>"
"<input type='submit' value='Ban'></form></td></tr>")
else:
responsedata += ("<td><form action='enableuser' method='POST'>"
"<input type='hidden' name='userid' value='"+userid+"'>"
"<input type='hidden' name='gameid' value='"+gameid+"'>"
"<input type='hidden' name='ingamesn' value='"+ingamesn+"'>"
"<input type='hidden' name='ipaddr' value='"+ipaddr+"'>"
"<input type='hidden' name='action' value='unban'>"
"<input type='submit' value='----- unban -----'></form></td></tr>")
responsedata += "</table>"
else:
responsedata += ("<td><form action='updatebanlist' method='POST'>"
"<input type='hidden' name='gameid' value='"+gameid+"'>"
"<input type='hidden' name='ipaddr' value='"+ipaddr+"'>"
"<input type='hidden' name='action' value='ban'>"
"<input type='submit' value='Ban'></form></td></tr>")
responsedata += "</table></html>"
dbconn.close()
request.setHeader("Content-Type", "text/html; charset=utf-8")
return responsedata.encode('utf-8')
def enable_disable_user(self, request, enable=True):
address = request.getClientIP()
responsedata = ""
userid = request.args['userid'][0]
gameid = request.args['gameid'][0].upper()
ingamesn = request.args['ingamesn'][0]
if not userid.isdigit() or not gameid.isalnum():
logger.log(logging.INFO,address+" Bad data "+userid+" "+gameid)
return "Bad data"
dbconn = sqlite3.connect('gpcm.db')
if enable:
dbconn.cursor().execute('update users set enabled=1 '
'where gameid=? and userid=?',(gameid,userid))
responsedata = "Enabled %s with gameid=%s, userid=%s" % \
(ingamesn,gameid,userid)
else:
dbconn.cursor().execute('update users set enabled=0 '
'where gameid=? and userid=?',(gameid,userid))
responsedata = "Disabled %s with gameid=%s, userid=%s" % \
(ingamesn,gameid,userid)
dbconn.commit()
dbconn.close()
logger.log(logging.INFO,address+" "+responsedata)
request.setHeader("Content-Type", "text/html; charset=utf-8")
request.setHeader("Location", "/banhammer")
request.setResponseCode(303)
return responsedata
def render_GET(self, request):
if not adminpageconf:
self.render_not_available(request)
return ""
if not self.is_authorized(request):
return ""
title = None
response = ''
if request.path == "/whitelist":
title = 'AltWfc Whitelist'
response = self.render_whitelist(request)
elif request.path == "/banhammer":
title = 'AltWfc Blacklist'
response = self.render_blacklist(request)
return self.get_header(title) + response + self.get_footer()
def render_POST(self, request):
if not adminpageconf:
self.render_not_available(request)
return ""
if not self.is_authorized(request):
return ""
if request.path == "/updatewhitelist":
return self.update_whitelist(request)
elif request.path == "/enableuser":
return self.enable_disable_user(request, True)
elif request.path == "/disableuser":
return self.enable_disable_user(request, False)
else:
return self.get_header() + self.get_footer()
if request.path == "/updatebanlist":
return self.update_banlist(request)
request.setResponseCode(500)
return "wrong url path"
port = 9009
class AdminPageServer(object):
def start(self):
site = server.Site(AdminPage(self))
reactor.listenTCP(port, site)
logger.log(logging.INFO, "Now listening for connections on port %d...", port)
reactor.listenTCP(9009, site)
try:
if reactor.running == False:
reactor.run(installSignalHandlers=0)