2024-12-06 21:07:42 +10:00

217 lines
8.7 KiB
Python

from typing import LiteralString
from allianceauth.eveonline.models import EveCharacter
from allianceauth.services.hooks import NameFormatter
from allianceauth.services.modules.mumble.managers import MumbleManager
from django.db import models
from allianceauth.services.abstract import AbstractServiceModel
import logging
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
logger = logging.getLogger(__name__)
class MumbleUser(AbstractServiceModel):
class HashFunction(models.TextChoices):
SHA256 = 'bcrypt-sha256', _('SHA256')
SHA1 = 'sha1', _('SHA1')
user = models.OneToOneField(
User,
primary_key=True,
on_delete=models.CASCADE,
related_name='mumble'
)
username = models.CharField(max_length=254, unique=True)
pwhash = models.CharField(max_length=90)
hashfn = models.CharField(
max_length=15,
choices=HashFunction.choices,
default=HashFunction.SHA256)
certhash = models.CharField(
verbose_name="Certificate Hash",
max_length=254,blank=True, null=True, editable=False,
help_text="Hash of Mumble client certificate as presented when user authenticates")
release = models.TextField(
verbose_name="Mumble Release",
blank=True, null=True, editable=False,
help_text="Client release. For official releases, this equals the version. For snapshots and git compiles, this will be something else.")
version = models.IntegerField(
verbose_name="Mumble Version",
blank=True, null=True, editable=False,
help_text="Client version. Major version in upper 16 bits, followed by 8 bits of minor version and 8 bits of patchlevel. Version 1.2.3 = 0x010203.")
last_connect = models.DateTimeField(
verbose_name="Last Connection",
blank=True, null=True, editable=False,
help_text="Timestamp of the users Last Connection to Mumble")
last_disconnect = models.DateTimeField(
verbose_name="Last Disconnection",
blank=True, null=True, editable=False,
help_text="Timestamp of the users Last Disconnection from Mumble")
objects = MumbleManager()
def __str__(self) -> str:
return f"{self.username}"
def update_password(self, password=None) -> None:
init_password = password
logger.debug(f"Updating mumble user {self.user} password.")
if not password:
password = MumbleManager.generate_random_pass()
pwhash = MumbleManager.gen_pwhash(password)
logger.debug(f"Proceeding with mumble user {self.user} password update - pwhash starts with {pwhash[0:5]}")
self.pwhash = pwhash
self.hashfn = self.HashFunction.SHA256
self.save()
if init_password is None:
self.credentials.update({'username': self.username, 'password': password})
def reset_password(self):
self.update_password()
def group_string(self) -> LiteralString:
"""Return a Mumble Safe Formatted List of Groups
This used to be a ModelField, generated on the fly now with DjangoAuthenticatorTM
Returns:
LiteralString: Mumble Safe Formatted List of Groups
"""
groups_str = [self.user.profile.state.name]
for group in self.user.groups.all():
groups_str.append(str(group.name))
return ','.join({g.replace(' ', '-') for g in groups_str})
def get_display_name(self):
from .auth_hooks import MumbleService
return NameFormatter(MumbleService(), self.user).format_name()
class Meta:
verbose_name = _("User")
verbose_name_plural = _("Users")
permissions = (
("access_mumble", "Can access the Mumble service"),
("view_connection_history", "Can access the connection history of the Mumble service"),
)
class TempLink(models.Model):
expires = models.DateTimeField(_("Expiry"), auto_now=False, auto_now_add=False)
link_ref = models.CharField(max_length=20)
creator = models.ForeignKey(EveCharacter, on_delete=models.SET_NULL, null=True, default=None)
class Meta:
permissions = (("create_new_links", "Can Create Temp Links"),)
def __str__(self):
return f"Link {self.link_ref} - {self.expires}"
class TempUser(models.Model):
name = models.CharField(max_length=200) # Display name to show
username = models.CharField(max_length=254, unique=True)
pwhash = models.CharField(max_length=90)
hashfn = models.CharField(
max_length=15,
choices=MumbleUser.HashFunction.choices,
default=MumbleUser.HashFunction.SHA256)
certhash = models.CharField(
verbose_name="Certificate Hash",
max_length=254,blank=True, null=True, editable=False,
help_text="Hash of Mumble client certificate as presented when user authenticates")
release = models.TextField(
verbose_name="Mumble Release",
blank=True, null=True, editable=False,
help_text="Client release. For official releases, this equals the version. For snapshots and git compiles, this will be something else.")
version = models.IntegerField(
verbose_name="Mumble Version",
blank=True, null=True, editable=False,
help_text="Client version. Major version in upper 16 bits, followed by 8 bits of minor version and 8 bits of patchlevel. Version 1.2.3 = 0x010203.")
last_connect = models.DateTimeField(
verbose_name="Last Connection",
blank=True, null=True, editable=False,
help_text="Timestamp of the users Last Connection to Mumble")
last_disconnect = models.DateTimeField(
verbose_name="Last Disconnection",
blank=True, null=True, editable=False,
help_text="Timestamp of the users Last Disconnection from Mumble")
expires = models.DateTimeField(_("Expiry"), auto_now=False, auto_now_add=False)
templink = models.ForeignKey(TempLink, on_delete=models.CASCADE, null=True, default=None)
character_id = models.IntegerField(default=None, blank=True, null=True)
def __str__(self) -> str:
return f"Temp User: {self.username} - {self.name}"
class IdlerHandler(models.Model):
name = models.CharField(_("Name"), max_length=50)
enabled = models.BooleanField(_("Enabled"), default=False)
seconds = models.SmallIntegerField(_("Idle Seconds"), default=3600)
interval = models.SmallIntegerField(_("Run Interval"), default=60)
channel = models.SmallIntegerField(_("AFK Channel"))
denylist = models.BooleanField(_(""), default=True)
list = models.CharField(_(""), max_length=50, default="")
class Meta:
verbose_name = _("Idler Handler")
verbose_name_plural = _("Idler Handlers")
default_permissions = ()
def __str__(self) -> str:
return f"{self.name}"
class MumbleServerServer(models.Model): # This will clash with ICE MumbleServer
class ServerVersion(models.TextChoices):
MUMBLESERVER_ICE = 'MumbleServer.ice', _('MumbleServer.ice (Mumble >=1.5.17)')
MURMUR_ICE = 'Murmur.Ice', _('Murmur.Ice (Mumble <=1.5.17)')
name = models.CharField(max_length=50)
ip = models.GenericIPAddressField(
verbose_name=_("Host IP Address"),
protocol="both",
unpack_ipv4=False,
default="127.0.0.1")
endpoint = models.GenericIPAddressField(
verbose_name=_("Endpoint IP Address"),
protocol="both",
unpack_ipv4=False,
default="127.0.0.1")
port = models.PositiveSmallIntegerField(verbose_name=_("Port"), default=6502)
secret = models.CharField(verbose_name=_("ICE Secret"), max_length=50)
watchdog = models.SmallIntegerField(verbose_name=_("Watchdog Interval"), default=30)
slice = models.CharField(
max_length=16,
choices=ServerVersion.choices,
default=ServerVersion.MUMBLESERVER_ICE)
virtual_servers = models.CharField(
verbose_name=_("Virtual Servers"),
max_length=50,
default="1")
avatar_enable = models.BooleanField(
verbose_name=_("Enable EVE Avatars"),
default=True)
reject_on_error = models.BooleanField(
verbose_name=_("Reject Unauthenticated"),
default=True)
offset = models.IntegerField(
verbose_name=_("ID Offset"),
default=1000000000)
idler_handler = models.ForeignKey(
IdlerHandler,
verbose_name=_("Idler Handler"),
on_delete=models.SET_NULL,
null=True,
blank=True)
class Meta:
verbose_name = _("Mumble Server")
verbose_name_plural = _("Mumble Servers")
default_permissions = ()
def __str__(self) -> str:
return f"{self.name}"
def virtual_servers_list(self) -> list:
return [int(num) for num in self.virtual_servers.replace(",", " ").split() if num]