forked from Minecraft/minecraft_manager
453 lines
22 KiB
Python
453 lines
22 KiB
Python
from __future__ import absolute_import
|
|
|
|
import datetime
|
|
import logging
|
|
|
|
from django.apps import apps
|
|
from django.contrib.auth import update_session_auth_hash
|
|
from django.contrib.auth.forms import PasswordChangeForm
|
|
from django.contrib.auth.models import User
|
|
from django.forms import modelform_factory
|
|
from django.http import JsonResponse, HttpResponse
|
|
from django.utils import timezone
|
|
from django.views.generic import View
|
|
|
|
import minecraft_manager.api.api as mcm_api
|
|
import minecraft_manager.external.stats as mcm_stats
|
|
import minecraft_manager.forms as mcm_forms
|
|
import minecraft_manager.utils as mcm_utils
|
|
from minecraft_manager.api.models import Token
|
|
from minecraft_manager.models import Player, UserSettings, Application, IP, Ticket, Note
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def request_allowed(request, permission):
|
|
is_authenticated = False
|
|
if hasattr(request, 'user'):
|
|
if hasattr(request.user, 'is_authenticated'):
|
|
is_authenticated = request.user.is_authenticated
|
|
get = request.GET
|
|
post = request.POST
|
|
request_password = None
|
|
if 'api' in get:
|
|
request_password = get['api']
|
|
elif 'api' in post:
|
|
request_password = post['api']
|
|
token_permission = False
|
|
if Token.objects.filter(active=True, key=request_password).exists():
|
|
token = Token.objects.get(active=True, key=request_password)
|
|
token_permission = getattr(token, permission, False)
|
|
return is_authenticated or token_permission
|
|
|
|
|
|
def clean(model, data):
|
|
cleaned = {}
|
|
for d in data:
|
|
attr = d
|
|
if '__' in d:
|
|
attr = d.split('__')[0]
|
|
if hasattr(model, attr) and attr != "api":
|
|
cleaned[d] = data[d]
|
|
return cleaned
|
|
|
|
|
|
class WebAPI(View):
|
|
|
|
def get(self, request, keyword):
|
|
get = request.GET
|
|
data = {'success': False, 'message': 'API failed'}
|
|
if request_allowed(request, 'web_get_permission'):
|
|
keyword = keyword.lower()
|
|
if keyword == 'log':
|
|
html_global = ""
|
|
html_staff = ""
|
|
chats = mcm_api.get_chats(request.user.usersettings.default_timezone)
|
|
if chats:
|
|
for g in chats['global']:
|
|
g['text'] = g['text'].replace("<", "<").replace(">", ">")
|
|
if request.user.usersettings.show_timestamp_chat:
|
|
html_global += "<div>[{0}] {1}</div>".format(g['date'], g['text'])
|
|
else:
|
|
html_global += "<div data-toggle='tooltip' title='{0}' data-placement='left'>{1}</div>".format(g['date'], g['text'])
|
|
for s in chats['staff']:
|
|
s['text'] = s['text'].replace("<", "<").replace(">", ">")
|
|
if request.user.usersettings.show_timestamp_chat:
|
|
html_staff += "<div>[{0}] {1}</div>".format(s['date'], s['text'])
|
|
else:
|
|
html_staff += "<div data-toggle='tooltip' title='{0}' data-placement='left'>{1}</div>".format(s['date'], s['text'])
|
|
html = {'global': html_global, 'staff': html_staff}
|
|
data = {'chats': chats, 'html': html}
|
|
elif keyword == 'online':
|
|
query = mcm_api.get_query()
|
|
html = ""
|
|
for p in query['players']:
|
|
html += "<div class='label label-primary'>{0}</div>".format(p)
|
|
html += "<br/>"
|
|
data = {'query': query, 'html': html}
|
|
elif keyword == "coreprotect":
|
|
if 'username' in get and 'ip' in get:
|
|
user = User.objects.get(username=get['username'])
|
|
if user.is_active and user.usersettings.last_ip == get['ip']:
|
|
data = {'success': True, 'message': self.access_level(user)}
|
|
else:
|
|
data = {'success': False, 'message': 'Parameters not set'}
|
|
else:
|
|
data = {'message': 'Not Authorized', 'success': False}
|
|
return JsonResponse(data)
|
|
|
|
def post(self, request, keyword):
|
|
post = request.POST
|
|
data = {}
|
|
if request_allowed(request, 'web_post_permission'):
|
|
keyword = keyword.lower()
|
|
if keyword == 'settings' and request.user.usersettings:
|
|
for s in [a for a in dir(UserSettings) if not a.startswith('__') and not callable(getattr(UserSettings,a))]:
|
|
if s in post:
|
|
setattr(request.user.usersettings, s, post[s])
|
|
request.user.usersettings.save()
|
|
data = {'success': True, 'message': 'User Settings saved'}
|
|
elif keyword == 'password':
|
|
form = PasswordChangeForm(request.user, post)
|
|
if form.is_valid():
|
|
user = form.save()
|
|
update_session_auth_hash(request, user)
|
|
return HttpResponse("success")
|
|
else:
|
|
return HttpResponse(form.as_p())
|
|
elif keyword == 'alert':
|
|
form = mcm_forms.AlertForm(request.POST)
|
|
if form.is_valid():
|
|
if mcm_api.create_alert(form.cleaned_data['message']):
|
|
data = {'success': True}
|
|
else:
|
|
data = {'success': False, 'message': 'Could not create Alerts'}
|
|
else:
|
|
data = {'success': False, 'message': 'Invalid Message'}
|
|
elif keyword == "discord":
|
|
if 'message' in post:
|
|
ping = post['ping'] if 'ping' in post else False
|
|
mcm_api.discord_notification(post['message'], ping=ping)
|
|
data = {'success': True, 'message': "Success", 'extra': {'message': post['message'], 'ping': ping}}
|
|
else:
|
|
data = {'success': False, 'message': 'No message supplied'}
|
|
else:
|
|
data = {'success': True, 'message': 'Model set to "{0}"'.format(keyword)}
|
|
else:
|
|
data = {'message': 'Not Authorized', 'success': False}
|
|
return JsonResponse(data)
|
|
|
|
def access_level(self, user):
|
|
access = {'cpp': False, 'cpf': False, 'cpa': False}
|
|
if user.has_perm('minecraft_manager.coreprotect_partial'):
|
|
access['cpp'] = True
|
|
if user.has_perm('minecraft_manager.coreprotect_full'):
|
|
access['cpf'] = True
|
|
if user.has_perm('minecraft_manager.coreprotect_activity'):
|
|
access['cpa'] = True
|
|
return access
|
|
|
|
|
|
class PluginAPI(View):
|
|
|
|
def get(self, request, keyword):
|
|
json = {'status': True, 'message': '', 'extra': ''}
|
|
if request_allowed(request, 'plugin_get_permission'):
|
|
get = request.GET
|
|
keyword = keyword.lower()
|
|
|
|
return JsonResponse(json)
|
|
|
|
def post(self, request, keyword):
|
|
json = {'status': True, 'message': '', 'extra': ''}
|
|
if request_allowed(request, 'plugin_post_permission'):
|
|
post = request.POST
|
|
keyword = keyword.lower()
|
|
if "application" == keyword:
|
|
if Application.objects.filter(username=post['username']).exists():
|
|
application = Application.objects.get(username=post['username'])
|
|
if application.accepted is not None:
|
|
json['status'] = False
|
|
json['message'] = "An application for {0} has already been acted on. Please contact Staff.".format(
|
|
post['username'])
|
|
return JsonResponse(json)
|
|
else:
|
|
application.accepted = None
|
|
application.age = post['age']
|
|
application.player_type = post['player_type']
|
|
application.ever_banned = False if post['ever_banned'] == "no" else True
|
|
application.ever_banned_explanation = post['ever_banned_explanation']
|
|
application.reference = post['reference']
|
|
application.read_rules = post['read_rules']
|
|
else:
|
|
application = Application(username=post['username'], age=post['age'],
|
|
player_type=post['player_type'],
|
|
ever_banned=False if post['ever_banned'] == "no" else True,
|
|
ever_banned_explanation= post['ever_banned_explanation'],
|
|
reference=post['reference'], read_rules=post['read_rules'])
|
|
application.save()
|
|
if Player.objects.filter(username__iexact=post['username']).exists():
|
|
player = Player.objects.get(username__iexact=post['username'])
|
|
player.application_id = application.id
|
|
player.save()
|
|
json['message'] = "{0}'s application was submitted.".format(application.username)
|
|
json['extra'] = application.id
|
|
msg = mcm_utils.build_application(application)
|
|
mcm_api.discord_mcm(message='New Application!', embed=msg)
|
|
elif "application_action" == keyword:
|
|
if Application.objects.filter(id=post['application_id']).exists():
|
|
application = Application.objects.get(id=post['application_id'])
|
|
if application.accepted is not None:
|
|
json['status'] = False
|
|
json['message'] = "Application was already {0}.".format(
|
|
"accepted" if post['action'] == "True" else "denied")
|
|
else:
|
|
application.accepted = True if post['action'] == "True" else False
|
|
application.save()
|
|
json['message'] = "Application was successfully {0}.".format(
|
|
"accepted" if post['action'] == "True" else "denied")
|
|
link = mcm_utils.full_reverse('application_info', application.id)
|
|
mcm_api.discord_mcm("{0}'s application ([#{1}]({4})) was {2} by {3}".format(application.username,
|
|
application.id,
|
|
"accepted" if post['action'] == "True" else "denied",
|
|
post['username'], link))
|
|
mcm_api.plugin("accept" if post['action'] == "True" else "deny", application.username)
|
|
else:
|
|
json['status'] = False
|
|
json['message'] = "No application found."
|
|
return JsonResponse(json)
|
|
elif "application_clear" == keyword:
|
|
if Application.objects.filter(id=post['application_id']).exists():
|
|
application = Application.objects.get(id=post['application_id'])
|
|
if application.accepted is True:
|
|
json['status'] = False
|
|
json['message'] = "An accepted application can't be cleared."
|
|
else:
|
|
application.accepted = None
|
|
application.save()
|
|
json['message'] = "Application was successfully cleared."
|
|
else:
|
|
json['status'] = False
|
|
json['message'] = "No application found."
|
|
return JsonResponse(json)
|
|
elif "login" == keyword:
|
|
player = Player.objects.filter(uuid=post['uuid']).exists()
|
|
new_player = False
|
|
if not player:
|
|
player = Player(uuid=post['uuid'], username=post['username'])
|
|
new_player = True
|
|
player.first_seen = timezone.now().strftime("%Y-%m-%d")
|
|
test_app = Application.objects.filter(username__iexact=post['username']).exists()
|
|
if test_app:
|
|
test_app = Application.objects.get(username__iexact=post['username'])
|
|
player.application = test_app
|
|
player.save()
|
|
else:
|
|
player = Player.objects.get(uuid=post['uuid'])
|
|
if player.username != post['username']:
|
|
user = User.objects.filter(username__iexact=player.username).exists()
|
|
if user:
|
|
user = User.objects.get(username__iexact=player.username)
|
|
user.username = post['username'].lower()
|
|
user.save()
|
|
mcm_api.create_alert("Name Change: {0} to {1}.".format(player.username, post['username']))
|
|
player.username = post['username']
|
|
if not player.application:
|
|
test_app = Application.objects.filter(username__iexact=post['username']).exists()
|
|
if test_app:
|
|
test_app = Application.objects.get(username__iexact=player.username)
|
|
player.application = test_app
|
|
player.save()
|
|
test_ip = IP.objects.filter(ip=post['ip'], player=player).exists()
|
|
last_used = datetime.date.today()
|
|
if not test_ip:
|
|
ip = IP(ip=post['ip'], player=player)
|
|
else:
|
|
ip = IP.objects.get(ip=post['ip'], player=player)
|
|
ip.last_used = last_used
|
|
ip.save()
|
|
player = Player.objects.get(uuid=post['uuid'])
|
|
player.last_seen = timezone.now().strftime("%Y-%m-%d")
|
|
player.save()
|
|
if new_player and ip.associated:
|
|
associated = []
|
|
for assoc in ip.associated:
|
|
if assoc.uuid is not player.uuid and assoc.is_banned:
|
|
associated.append(assoc)
|
|
if associated:
|
|
mcm_api.plugin("staff", "Server {0}'s IP matches the banned player(s) {1}".format(player.username, ", ".join([assoc.username for assoc in associated])))
|
|
mcm_api.discord_notification("{0}'s IP matches the banned player(s) {1}".format(player.username, ", ".join([assoc.username for assoc in associated])), ping=True)
|
|
json['status'] = True
|
|
json['message'] = "Updated {0}".format(post['username'])
|
|
elif "register" == keyword:
|
|
player = Player.objects.get(uuid=post['uuid'])
|
|
password = mcm_api.generate_password()
|
|
if player.auth_user:
|
|
player.auth_user.password = password
|
|
player.auth_user.is_active = True
|
|
player.auth_user.save()
|
|
json['message'] = password
|
|
else:
|
|
user = User.objects.create_user(username=player.username.lower(), password=password)
|
|
user.save()
|
|
player.auth_user = user
|
|
player.save()
|
|
json['message'] = password
|
|
elif "ticket" == keyword:
|
|
player = Player.objects.get(uuid=post['uuid'])
|
|
try:
|
|
ticket = Ticket(player=player, message=post['message'], x=post['x'], y=post['y'], z=post['z'], world=post['world'])
|
|
ticket.save()
|
|
json['message'] = "Ticket submitted."
|
|
link = mcm_utils.full_reverse('ticket_info', ticket.id)
|
|
msg = mcm_utils.build_ticket(ticket, link)
|
|
json['extra'] = {'id': ticket.id, 'link': link}
|
|
mcm_api.discord_mcm(embed=msg, ping=True)
|
|
except:
|
|
json['status'] = False
|
|
json['message'] = "Error while submitting ticket."
|
|
elif "warning" == keyword:
|
|
player = Player.objects.get(uuid=post['player'])
|
|
staff = Player.objects.get(uuid=post['staff'])
|
|
try:
|
|
warning = Note(player=player, message=post['message'], importance=post['severity'], staff=staff.auth_user)
|
|
warning.save()
|
|
json['message'] = "Warning issued."
|
|
link = mcm_utils.full_reverse('note_info', warning.id)
|
|
msg = mcm_utils.build_note(warning, link)
|
|
mcm_api.discord_mcm(embed=msg)
|
|
except Exception as ex:
|
|
json['status'] = False
|
|
json['message'] = "Error while issuing warning."
|
|
return JsonResponse(json)
|
|
|
|
|
|
class FormAPI(View):
|
|
|
|
def get(self, request, request_model):
|
|
html = ""
|
|
if request_allowed(request, 'form_get_permission'):
|
|
get = request.GET
|
|
model = None
|
|
for m in apps.get_app_config('minecraft_manager').get_models():
|
|
if m._meta.model_name.upper() == request_model.upper():
|
|
model = m
|
|
break
|
|
if model:
|
|
form = None
|
|
for modelform in mcm_forms.__all__():
|
|
if modelform.Meta.model == model:
|
|
form = modelform()
|
|
break
|
|
if not form:
|
|
form = modelform_factory(model, exclude=('id',))()
|
|
if 'as' in get:
|
|
html = getattr(form, 'as_{0}'.format(get['as']))()
|
|
else:
|
|
html = form.as_p()
|
|
return HttpResponse(html)
|
|
|
|
def post(self, request, request_model):
|
|
html = ""
|
|
if request_allowed(request, 'form_post_permission'):
|
|
post = request.POST
|
|
model = None
|
|
for m in apps.get_app_config('minecraft_manager').get_models():
|
|
if m._meta.model_name.upper() == request_model.upper():
|
|
model = m
|
|
break
|
|
if model:
|
|
form = None
|
|
for modelform in mcm_forms.__all__():
|
|
if modelform.Meta.model == model:
|
|
form = modelform(post)
|
|
break
|
|
if not form:
|
|
form = modelform_factory(model, exclude=('id',))(post)
|
|
if form.is_valid():
|
|
form.save()
|
|
html = "Saved"
|
|
else:
|
|
if 'as' in post:
|
|
html = getattr(form, 'as_{0}'.format(post['as']))()
|
|
else:
|
|
html = form.as_p()
|
|
return HttpResponse(html)
|
|
|
|
|
|
class ModelAPI(View):
|
|
|
|
def get(self, request, request_model):
|
|
json = []
|
|
if request_allowed(request, 'model_get_permission'):
|
|
get = request.GET
|
|
model = None
|
|
for m in apps.get_app_config('minecraft_manager').get_models():
|
|
if m._meta.model_name.upper() == request_model.upper():
|
|
model = m
|
|
break
|
|
if model:
|
|
keywords = clean(model, get)
|
|
objects = model.api.filter(**keywords).values() if getattr(model, 'api', False) else model.objects.filter(**keywords).values()
|
|
json = []
|
|
for value in objects:
|
|
try:
|
|
link = mcm_utils.full_reverse(f"{request_model}_info", value['id'])
|
|
value['link'] = link
|
|
except:
|
|
pass
|
|
json.append(value)
|
|
return JsonResponse(json, safe=False)
|
|
|
|
def post(self, request, request_model):
|
|
json = {"success": False, "message": ""}
|
|
if request_allowed(request, 'model_post_permission'):
|
|
post = request.POST
|
|
model = None
|
|
for m in apps.get_app_config('minecraft_manager').get_models():
|
|
if m._meta.model_name.upper() == request_model.upper():
|
|
model = m
|
|
break
|
|
if model:
|
|
keywords = clean(model, post)
|
|
if "id" in keywords:
|
|
try:
|
|
obj = model.objects.get(id=keywords["id"])
|
|
for key in keywords.keys():
|
|
setattr(obj, key, keywords[key])
|
|
obj.save()
|
|
json["success"] = True
|
|
json["message"] = "Model updated"
|
|
except Exception as ex:
|
|
print(ex)
|
|
json["message"] = "Could not update model"
|
|
else:
|
|
json["message"] = "Must provide an ID"
|
|
|
|
return JsonResponse(json)
|
|
|
|
|
|
class StatsAPI(View):
|
|
|
|
def get(self, request):
|
|
json = []
|
|
if request_allowed(request, 'stats_get_permission'):
|
|
get = request.GET
|
|
if 'stat' in get:
|
|
if 'uuid' in get:
|
|
json = mcm_stats.one_single(get['uuid'], get['stat'])
|
|
elif 'username' in get and Player.objects.filter(username__iexact=get['username']).exists():
|
|
uuid = Player.objects.get(username__iexact=get['username']).uuid
|
|
json = mcm_stats.one_single(uuid, get['stat'])
|
|
else:
|
|
json = mcm_stats.top_ten_stat(get['stat'])
|
|
elif 'uuid' in get:
|
|
json = mcm_stats.top_ten_player(get['uuid'])
|
|
elif 'username' in get:
|
|
uuid = Player.objects.get(username__iexact=get['username']).uuid
|
|
json = mcm_stats.top_ten_player(uuid)
|
|
return JsonResponse(json, safe=False)
|
|
|
|
def post(self, request):
|
|
pass
|