mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-09 12:30:15 +02:00
heccin squash
This commit is contained in:
parent
389b958ca7
commit
5d4df417c2
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('authentication', '0025_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='userprofile',
|
||||||
|
name='theme',
|
||||||
|
field=models.CharField(blank=True, default='', help_text='Bootstrap 5 Themes from https://bootswatch.com/ or Community Apps', max_length=200, verbose_name='Theme'),
|
||||||
|
),
|
||||||
|
]
|
@ -15,24 +15,30 @@ logger = logging.getLogger(__name__)
|
|||||||
class State(models.Model):
|
class State(models.Model):
|
||||||
name = models.CharField(max_length=32, unique=True)
|
name = models.CharField(max_length=32, unique=True)
|
||||||
permissions = models.ManyToManyField(Permission, blank=True)
|
permissions = models.ManyToManyField(Permission, blank=True)
|
||||||
priority = models.IntegerField(unique=True, help_text="Users get assigned the state with the highest priority available to them.")
|
priority = models.IntegerField(
|
||||||
|
unique=True, help_text="Users get assigned the state with the highest priority available to them."
|
||||||
|
)
|
||||||
|
|
||||||
member_characters = models.ManyToManyField(EveCharacter, blank=True,
|
member_characters = models.ManyToManyField(
|
||||||
help_text="Characters to which this state is available.")
|
EveCharacter, blank=True, help_text="Characters to which this state is available."
|
||||||
member_corporations = models.ManyToManyField(EveCorporationInfo, blank=True,
|
)
|
||||||
help_text="Corporations to whose members this state is available.")
|
member_corporations = models.ManyToManyField(
|
||||||
member_alliances = models.ManyToManyField(EveAllianceInfo, blank=True,
|
EveCorporationInfo, blank=True, help_text="Corporations to whose members this state is available."
|
||||||
help_text="Alliances to whose members this state is available.")
|
)
|
||||||
member_factions = models.ManyToManyField(EveFactionInfo, blank=True,
|
member_alliances = models.ManyToManyField(
|
||||||
help_text="Factions to whose members this state is available.")
|
EveAllianceInfo, blank=True, help_text="Alliances to whose members this state is available."
|
||||||
|
)
|
||||||
|
member_factions = models.ManyToManyField(
|
||||||
|
EveFactionInfo, blank=True, help_text="Factions to whose members this state is available."
|
||||||
|
)
|
||||||
public = models.BooleanField(default=False, help_text="Make this state available to any character.")
|
public = models.BooleanField(default=False, help_text="Make this state available to any character.")
|
||||||
|
|
||||||
objects = StateManager()
|
objects = StateManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['-priority']
|
ordering = ["-priority"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def available_to_character(self, character):
|
def available_to_character(self, character):
|
||||||
@ -48,11 +54,11 @@ class State(models.Model):
|
|||||||
super().delete(**kwargs)
|
super().delete(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_guest_state():
|
def get_guest_state() -> State:
|
||||||
try:
|
try:
|
||||||
return State.objects.get(name='Guest')
|
return State.objects.get(name="Guest")
|
||||||
except State.DoesNotExist:
|
except State.DoesNotExist:
|
||||||
return State.objects.create(name='Guest', priority=0, public=True)
|
return State.objects.create(name="Guest", priority=0, public=True)
|
||||||
|
|
||||||
|
|
||||||
def get_guest_state_pk():
|
def get_guest_state_pk():
|
||||||
@ -60,76 +66,58 @@ def get_guest_state_pk():
|
|||||||
|
|
||||||
|
|
||||||
class UserProfile(models.Model):
|
class UserProfile(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Language(models.TextChoices):
|
class Language(models.TextChoices):
|
||||||
"""
|
"""
|
||||||
Choices for UserProfile.language
|
Choices for UserProfile.language
|
||||||
"""
|
"""
|
||||||
# Sorted by Language Code alphabetical order + English at top
|
|
||||||
ENGLISH = 'en', _('English')
|
|
||||||
CZECH = 'cs-cz', _("Czech") # Not yet at 50% translated
|
|
||||||
GERMAN = 'de', _('German')
|
|
||||||
SPANISH = 'es', _('Spanish')
|
|
||||||
ITALIAN = 'it-it', _('Italian')
|
|
||||||
JAPANESE = 'ja', _('Japanese')
|
|
||||||
KOREAN = 'ko-kr', _('Korean')
|
|
||||||
FRENCH = 'fr-fr', _('French')
|
|
||||||
RUSSIAN = 'ru', _('Russian')
|
|
||||||
DUTCH = 'nl-nl', _("Dutch")
|
|
||||||
POLISH = 'pl-pl', _("Polish")
|
|
||||||
UKRAINIAN = 'uk', _('Ukrainian')
|
|
||||||
CHINESE = 'zh-hans', _('Simplified Chinese')
|
|
||||||
|
|
||||||
user = models.OneToOneField(
|
# Sorted by Language Code alphabetical order + English at top
|
||||||
User,
|
ENGLISH = "en", _("English")
|
||||||
related_name='profile',
|
CZECH = "cs-cz", _("Czech") # Not yet at 50% translated
|
||||||
on_delete=models.CASCADE)
|
GERMAN = "de", _("German")
|
||||||
main_character = models.OneToOneField(
|
SPANISH = "es", _("Spanish")
|
||||||
EveCharacter,
|
ITALIAN = "it-it", _("Italian")
|
||||||
blank=True,
|
JAPANESE = "ja", _("Japanese")
|
||||||
null=True,
|
KOREAN = "ko-kr", _("Korean")
|
||||||
on_delete=models.SET_NULL)
|
FRENCH = "fr-fr", _("French")
|
||||||
state = models.ForeignKey(
|
RUSSIAN = "ru", _("Russian")
|
||||||
State,
|
DUTCH = "nl-nl", _("Dutch")
|
||||||
on_delete=models.SET_DEFAULT,
|
POLISH = "pl-pl", _("Polish")
|
||||||
default=get_guest_state_pk)
|
UKRAINIAN = "uk", _("Ukrainian")
|
||||||
language = models.CharField(
|
CHINESE = "zh-hans", _("Simplified Chinese")
|
||||||
_("Language"), max_length=10,
|
|
||||||
choices=Language.choices,
|
user = models.OneToOneField(User, related_name="profile", on_delete=models.CASCADE)
|
||||||
blank=True,
|
main_character = models.OneToOneField(EveCharacter, blank=True, null=True, on_delete=models.SET_NULL)
|
||||||
default='')
|
state = models.ForeignKey(State, on_delete=models.SET_DEFAULT, default=get_guest_state_pk)
|
||||||
night_mode = models.BooleanField(
|
language = models.CharField(_("Language"), max_length=10, choices=Language.choices, blank=True, default="")
|
||||||
_("Night Mode"),
|
night_mode = models.BooleanField(_("Night Mode"), blank=True, null=True)
|
||||||
blank=True,
|
|
||||||
null=True)
|
|
||||||
theme = models.CharField(
|
theme = models.CharField(
|
||||||
_("Theme"),
|
_("Theme"),
|
||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="Bootstrap 5 Themes from https://bootswatch.com/ or Community Apps"
|
default="",
|
||||||
|
help_text="Bootstrap 5 Themes from https://bootswatch.com/ or Community Apps",
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
default_permissions = ('change',)
|
default_permissions = ("change",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return str(self.user)
|
return str(self.user)
|
||||||
|
|
||||||
def assign_state(self, state=None, commit=True):
|
def assign_state(self, state=None, commit=True) -> None:
|
||||||
if not state:
|
if not state:
|
||||||
state = State.objects.get_for_user(self.user)
|
state = State.objects.get_for_user(self.user)
|
||||||
if self.state != state:
|
if self.state != state:
|
||||||
self.state = state
|
self.state = state
|
||||||
if commit:
|
if commit:
|
||||||
logger.info(f'Updating {self.user} state to {self.state}')
|
logger.info(f"Updating {self.user} state to {self.state}")
|
||||||
self.save(update_fields=['state'])
|
self.save(update_fields=["state"])
|
||||||
notify(
|
notify(
|
||||||
self.user,
|
self.user,
|
||||||
_(f'State changed to: {state}'),
|
_(f"State changed to: {state}"),
|
||||||
_('Your user\'s state is now: %(state)s')
|
_("Your user's state is now: %(state)s") % ({"state": state}),
|
||||||
% ({'state': state}),
|
"info",
|
||||||
'info'
|
|
||||||
)
|
)
|
||||||
from allianceauth.authentication.signals import state_changed
|
from allianceauth.authentication.signals import state_changed
|
||||||
|
|
||||||
@ -137,34 +125,32 @@ class UserProfile(models.Model):
|
|||||||
# Clear all attribute caches and reload the model that will get passed to the signals!
|
# Clear all attribute caches and reload the model that will get passed to the signals!
|
||||||
self.refresh_from_db()
|
self.refresh_from_db()
|
||||||
|
|
||||||
state_changed.send(
|
state_changed.send(sender=self.__class__, user=self.user, state=self.state)
|
||||||
sender=self.__class__, user=self.user, state=self.state
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CharacterOwnership(models.Model):
|
class CharacterOwnership(models.Model):
|
||||||
|
character = models.OneToOneField(EveCharacter, on_delete=models.CASCADE, related_name="character_ownership")
|
||||||
|
|
||||||
character = models.OneToOneField(EveCharacter, on_delete=models.CASCADE, related_name='character_ownership')
|
|
||||||
owner_hash = models.CharField(max_length=28, unique=True)
|
owner_hash = models.CharField(max_length=28, unique=True)
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='character_ownerships')
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="character_ownerships")
|
||||||
|
|
||||||
objects = CharacterOwnershipManager()
|
objects = CharacterOwnershipManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
default_permissions = ('change', 'delete')
|
default_permissions = ("change", "delete")
|
||||||
ordering = ['user', 'character__character_name']
|
ordering = ["user", "character__character_name"]
|
||||||
def __str__(self):
|
|
||||||
|
def __str__(self) -> str:
|
||||||
return f"{self.user}: {self.character}"
|
return f"{self.user}: {self.character}"
|
||||||
|
|
||||||
|
|
||||||
class OwnershipRecord(models.Model):
|
class OwnershipRecord(models.Model):
|
||||||
character = models.ForeignKey(EveCharacter, on_delete=models.CASCADE, related_name='ownership_records')
|
character = models.ForeignKey(EveCharacter, on_delete=models.CASCADE, related_name="ownership_records")
|
||||||
owner_hash = models.CharField(max_length=28, db_index=True)
|
owner_hash = models.CharField(max_length=28, db_index=True)
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='ownership_records')
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="ownership_records")
|
||||||
created = models.DateTimeField(auto_now=True)
|
created = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['-created']
|
ordering = ["-created"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f"{self.user}: {self.character} on {self.created}"
|
return f"{self.user}: {self.character} on {self.created}"
|
||||||
|
@ -34,6 +34,7 @@ class CorpStats(models.Model):
|
|||||||
last_update = models.DateTimeField(auto_now=True)
|
last_update = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
objects = CorpStatsManager()
|
objects = CorpStatsManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
('view_corp_corpstats', 'Can view corp stats of their corporation.'),
|
('view_corp_corpstats', 'Can view corp stats of their corporation.'),
|
||||||
@ -43,12 +44,10 @@ class CorpStats(models.Model):
|
|||||||
verbose_name = "corp stats"
|
verbose_name = "corp stats"
|
||||||
verbose_name_plural = "corp stats"
|
verbose_name_plural = "corp stats"
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"{self.__class__.__name__} for {self.corp}"
|
return f"{self.__class__.__name__} for {self.corp}"
|
||||||
|
|
||||||
def update(self):
|
def update(self) -> None:
|
||||||
try:
|
try:
|
||||||
c = self.token.get_esi_client(spec_file=SWAGGER_SPEC_PATH)
|
c = self.token.get_esi_client(spec_file=SWAGGER_SPEC_PATH)
|
||||||
assert c.Character.get_characters_character_id(character_id=self.token.character_id).result()['corporation_id'] == int(self.corp.corporation_id)
|
assert c.Character.get_characters_character_id(character_id=self.token.character_id).result()['corporation_id'] == int(self.corp.corporation_id)
|
||||||
@ -101,11 +100,11 @@ class CorpStats(models.Model):
|
|||||||
return self.members.count()
|
return self.members.count()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def user_count(self):
|
def user_count(self) -> int:
|
||||||
return len({m.main_character for m in self.members.all() if m.main_character})
|
return len({m.main_character for m in self.members.all() if m.main_character})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def registered_member_count(self):
|
def registered_member_count(self) -> int:
|
||||||
return len(self.registered_members)
|
return len(self.registered_members)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -121,7 +120,7 @@ class CorpStats(models.Model):
|
|||||||
return self.members.filter(pk__in=[m.pk for m in self.members.all() if not m.registered])
|
return self.members.filter(pk__in=[m.pk for m in self.members.all() if not m.registered])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def main_count(self):
|
def main_count(self) -> int:
|
||||||
return len(self.mains)
|
return len(self.mains)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -134,10 +133,10 @@ class CorpStats(models.Model):
|
|||||||
def can_update(self, user):
|
def can_update(self, user):
|
||||||
return self.token.user == user or self.visible_to(user)
|
return self.token.user == user or self.visible_to(user)
|
||||||
|
|
||||||
def corp_logo(self, size=128):
|
def corp_logo(self, size=128) -> str:
|
||||||
return self.corp.logo_url(size)
|
return self.corp.logo_url(size)
|
||||||
|
|
||||||
def alliance_logo(self, size=128):
|
def alliance_logo(self, size=128) -> str:
|
||||||
if self.corp.alliance:
|
if self.corp.alliance:
|
||||||
return self.corp.alliance.logo_url(size)
|
return self.corp.alliance.logo_url(size)
|
||||||
else:
|
else:
|
||||||
@ -154,11 +153,11 @@ class CorpMember(models.Model):
|
|||||||
unique_together = ('corpstats', 'character_id')
|
unique_together = ('corpstats', 'character_id')
|
||||||
ordering = ['character_name']
|
ordering = ['character_name']
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.character_name
|
return self.character_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def character(self):
|
def character(self) -> EveCharacter | None:
|
||||||
try:
|
try:
|
||||||
return EveCharacter.objects.get(character_id=self.character_id)
|
return EveCharacter.objects.get(character_id=self.character_id)
|
||||||
except EveCharacter.DoesNotExist:
|
except EveCharacter.DoesNotExist:
|
||||||
@ -179,20 +178,20 @@ class CorpMember(models.Model):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def registered(self):
|
def registered(self) -> bool:
|
||||||
return CharacterOwnership.objects.filter(character__character_id=self.character_id).exists()
|
return CharacterOwnership.objects.filter(character__character_id=self.character_id).exists()
|
||||||
|
|
||||||
def portrait_url(self, size=32):
|
def portrait_url(self, size=32) -> str:
|
||||||
return EveCharacter.generic_portrait_url(self.character_id, size)
|
return EveCharacter.generic_portrait_url(self.character_id, size)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def portrait_url_32(self):
|
def portrait_url_32(self) -> str:
|
||||||
return self.portrait_url(32)
|
return self.portrait_url(32)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def portrait_url_64(self):
|
def portrait_url_64(self) -> str:
|
||||||
return self.portrait_url(64)
|
return self.portrait_url(64)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def portrait_url_128(self):
|
def portrait_url_128(self) -> str:
|
||||||
return self.portrait_url(128)
|
return self.portrait_url(128)
|
||||||
|
@ -11,7 +11,6 @@ def random_default() -> float:
|
|||||||
|
|
||||||
|
|
||||||
class CronOffset(SingletonModel):
|
class CronOffset(SingletonModel):
|
||||||
|
|
||||||
minute = models.FloatField(_("Minute Offset"), default=random_default)
|
minute = models.FloatField(_("Minute Offset"), default=random_default)
|
||||||
hour = models.FloatField(_("Hour Offset"), default=random_default)
|
hour = models.FloatField(_("Hour Offset"), default=random_default)
|
||||||
day_of_month = models.FloatField(_("Day of Month Offset"), default=random_default)
|
day_of_month = models.FloatField(_("Day of Month Offset"), default=random_default)
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('custom_css', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='customcss',
|
||||||
|
name='css',
|
||||||
|
field=models.TextField(blank=True, default='', help_text='This CSS will be added to the site after the default CSS.', verbose_name='Your custom CSS'),
|
||||||
|
),
|
||||||
|
]
|
@ -22,6 +22,7 @@ class CustomCSS(SingletonModel):
|
|||||||
css = models.TextField(
|
css = models.TextField(
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name=_("Your custom CSS"),
|
verbose_name=_("Your custom CSS"),
|
||||||
|
default="",
|
||||||
help_text=_("This CSS will be added to the site after the default CSS."),
|
help_text=_("This CSS will be added to the site after the default CSS."),
|
||||||
)
|
)
|
||||||
timestamp = models.DateTimeField(auto_now=True)
|
timestamp = models.DateTimeField(auto_now=True)
|
||||||
@ -45,7 +46,7 @@ class CustomCSS(SingletonModel):
|
|||||||
|
|
||||||
return str(_("Custom CSS"))
|
return str(_("Custom CSS"))
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs) -> None:
|
||||||
"""
|
"""
|
||||||
Save method for CustomCSS
|
Save method for CustomCSS
|
||||||
|
|
||||||
@ -61,9 +62,7 @@ class CustomCSS(SingletonModel):
|
|||||||
|
|
||||||
if self.css and len(self.css.replace(" ", "")) > 0:
|
if self.css and len(self.css.replace(" ", "")) > 0:
|
||||||
# Write the custom CSS to a file
|
# Write the custom CSS to a file
|
||||||
custom_css_file = open(
|
custom_css_file = open(f"{settings.STATIC_ROOT}allianceauth/custom-styles.css", "w+")
|
||||||
f"{settings.STATIC_ROOT}allianceauth/custom-styles.css", "w+"
|
|
||||||
)
|
|
||||||
custom_css_file.write(self.compress_css())
|
custom_css_file.write(self.compress_css())
|
||||||
custom_css_file.close()
|
custom_css_file.close()
|
||||||
else:
|
else:
|
||||||
@ -105,9 +104,7 @@ class CustomCSS(SingletonModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Fragment values can loose zeros
|
# Fragment values can loose zeros
|
||||||
css = re.sub(
|
css = re.sub(pattern=r":\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;", repl=r":\1;", string=css)
|
||||||
pattern=r":\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;", repl=r":\1;", string=css
|
|
||||||
)
|
|
||||||
|
|
||||||
for rule in re.findall(pattern=r"([^{]+){([^}]*)}", string=css):
|
for rule in re.findall(pattern=r"([^{]+){([^}]*)}", string=css):
|
||||||
# We don't need spaces around operators
|
# We don't need spaces around operators
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# Generated by Django 1.11.6 on 2017-12-23 04:30
|
# Generated by Django 5.1.6 on 2025-03-05 01:45
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
@ -9,9 +10,9 @@ class Migration(migrations.Migration):
|
|||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('authentication', '0015_user_profiles'),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
('auth', '0008_alter_user_username_max_length'),
|
('authentication', '0025_v5squash'),
|
||||||
('eveonline', '0009_on_delete'),
|
('eveonline', '0019_v5squash'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
@ -27,15 +28,18 @@ class Migration(migrations.Migration):
|
|||||||
('alliance_name_source', models.CharField(choices=[('ticker', 'Ticker'), ('name', 'Full name')], default='name', max_length=20)),
|
('alliance_name_source', models.CharField(choices=[('ticker', 'Ticker'), ('name', 'Full name')], default='name', max_length=20)),
|
||||||
('replace_spaces', models.BooleanField(default=False)),
|
('replace_spaces', models.BooleanField(default=False)),
|
||||||
('replace_spaces_with', models.CharField(blank=True, default='', help_text='Any spaces in the group name will be replaced with this.', max_length=10)),
|
('replace_spaces_with', models.CharField(blank=True, default='', help_text='Any spaces in the group name will be replaced with this.', max_length=10)),
|
||||||
|
('alliance_managed_groups', models.ManyToManyField(help_text="A list of alliance groups created and maintained by this AutogroupConfig. You should not edit this list unless you know what you're doing.", related_name='alliance_managed_config', through='eve_autogroups.ManagedAllianceGroup', to='auth.group')),
|
||||||
|
('corp_managed_groups', models.ManyToManyField(help_text="A list of corporation groups created and maintained by this AutogroupConfig. You should not edit this list unless you know what you're doing.", related_name='corp_managed_config', through='eve_autogroups.ManagedCorpGroup', to='auth.group')),
|
||||||
|
('states', models.ManyToManyField(related_name='autogroups', to='authentication.state')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='ManagedAllianceGroup',
|
name='ManagedAllianceGroup',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('alliance', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveAllianceInfo')),
|
('alliance', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.eveallianceinfo')),
|
||||||
('config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eve_autogroups.AutogroupsConfig')),
|
('config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eve_autogroups.autogroupsconfig')),
|
||||||
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')),
|
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.group')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
@ -45,27 +49,12 @@ class Migration(migrations.Migration):
|
|||||||
name='ManagedCorpGroup',
|
name='ManagedCorpGroup',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eve_autogroups.AutogroupsConfig')),
|
('config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eve_autogroups.autogroupsconfig')),
|
||||||
('corp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCorporationInfo')),
|
('corp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.evecorporationinfo')),
|
||||||
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')),
|
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.group')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
|
||||||
model_name='autogroupsconfig',
|
|
||||||
name='alliance_managed_groups',
|
|
||||||
field=models.ManyToManyField(help_text="A list of alliance groups created and maintained by this AutogroupConfig. You should not edit this list unless you know what you're doing.", related_name='alliance_managed_config', through='eve_autogroups.ManagedAllianceGroup', to='auth.Group'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='autogroupsconfig',
|
|
||||||
name='corp_managed_groups',
|
|
||||||
field=models.ManyToManyField(help_text="A list of corporation groups created and maintained by this AutogroupConfig. You should not edit this list unless you know what you're doing.", related_name='corp_managed_config', through='eve_autogroups.ManagedCorpGroup', to='auth.Group'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='autogroupsconfig',
|
|
||||||
name='states',
|
|
||||||
field=models.ManyToManyField(related_name='autogroups', to='authentication.State'),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
@ -81,23 +81,23 @@ class AutogroupsConfig(models.Model):
|
|||||||
|
|
||||||
objects = AutogroupsConfigManager()
|
objects = AutogroupsConfigManager()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return 'States: ' + (' '.join(list(self.states.all().values_list('name', flat=True))) if self.pk else str(None))
|
return f"States: {' '.join(self.states.all().values_list('name', flat=True)) if self.pk else 'None'}"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs) -> None:
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
def update_all_states_group_membership(self):
|
def update_all_states_group_membership(self) -> None:
|
||||||
list(map(self.update_group_membership_for_state, self.states.all()))
|
list(map(self.update_group_membership_for_state, self.states.all()))
|
||||||
|
|
||||||
def update_group_membership_for_state(self, state: State):
|
def update_group_membership_for_state(self, state: State):
|
||||||
list(map(self.update_group_membership_for_user, get_users_for_state(state)))
|
list(map(self.update_group_membership_for_user, get_users_for_state(state)))
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def update_group_membership_for_user(self, user: User):
|
def update_group_membership_for_user(self, user: User) -> None:
|
||||||
self.update_alliance_group_membership(user)
|
self.update_alliance_group_membership(user)
|
||||||
self.update_corp_group_membership(user)
|
self.update_corp_group_membership(user)
|
||||||
|
|
||||||
@ -235,9 +235,10 @@ class ManagedGroup(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f"Managed Group: {self.group.name}"
|
return f"Managed Group: {self.group.name}"
|
||||||
|
|
||||||
|
|
||||||
class ManagedCorpGroup(ManagedGroup):
|
class ManagedCorpGroup(ManagedGroup):
|
||||||
corp = models.ForeignKey(EveCorporationInfo, on_delete=models.CASCADE)
|
corp = models.ForeignKey(EveCorporationInfo, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
@ -20,14 +20,14 @@ class Migration(migrations.Migration):
|
|||||||
name='alliance_ticker',
|
name='alliance_ticker',
|
||||||
field=models.CharField(blank=True, default='', max_length=5),
|
field=models.CharField(blank=True, default='', max_length=5),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
|
||||||
model_name='evecharacter',
|
|
||||||
name='faction_id',
|
|
||||||
field=models.PositiveIntegerField(blank=True, default=None, null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='evecharacter',
|
model_name='evecharacter',
|
||||||
name='faction_name',
|
name='faction_name',
|
||||||
field=models.CharField(blank=True, default='', max_length=254),
|
field=models.CharField(blank=True, default='', max_length=254),
|
||||||
),
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='evecharacter',
|
||||||
|
name='faction_id',
|
||||||
|
field=models.PositiveIntegerField(blank=True, default=None, null=True),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
# Generated by Django 5.1.6 on 2025-03-04 03:06
|
# Generated by Django 5.1.6 on 2025-03-05 01:03
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
@ -12,7 +11,7 @@ class Migration(migrations.Migration):
|
|||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
('auth', '__first__'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
@ -29,25 +28,6 @@ class Migration(migrations.Migration):
|
|||||||
'indexes': [models.Index(fields=['executor_corp_id'], name='eveonline_e_executo_7f3280_idx')],
|
'indexes': [models.Index(fields=['executor_corp_id'], name='eveonline_e_executo_7f3280_idx')],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
|
||||||
name='EveCharacter',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('character_id', models.PositiveIntegerField(unique=True)),
|
|
||||||
('character_name', models.CharField(db_index=True, max_length=254)),
|
|
||||||
('corporation_id', models.PositiveIntegerField()),
|
|
||||||
('corporation_name', models.CharField(max_length=254)),
|
|
||||||
('corporation_ticker', models.CharField(max_length=5)),
|
|
||||||
('alliance_id', models.PositiveIntegerField(blank=True, default=None, null=True)),
|
|
||||||
('alliance_name', models.CharField(blank=True, default='', max_length=254, null=True)),
|
|
||||||
('alliance_ticker', models.CharField(blank=True, default='', max_length=5, null=True)),
|
|
||||||
('faction_id', models.PositiveIntegerField(blank=True, default=None, null=True)),
|
|
||||||
('faction_name', models.CharField(blank=True, default='', max_length=254, null=True)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'indexes': [models.Index(fields=['corporation_id'], name='eveonline_e_corpora_cb4cd9_idx'), models.Index(fields=['alliance_id'], name='eveonline_e_allianc_39ee2a_idx'), models.Index(fields=['corporation_name'], name='eveonline_e_corpora_893c60_idx'), models.Index(fields=['alliance_name'], name='eveonline_e_allianc_63fd98_idx'), models.Index(fields=['faction_id'], name='eveonline_e_faction_d5274e_idx')],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='EveFactionInfo',
|
name='EveFactionInfo',
|
||||||
fields=[
|
fields=[
|
||||||
@ -71,4 +51,23 @@ class Migration(migrations.Migration):
|
|||||||
'indexes': [models.Index(fields=['ceo_id'], name='eveonline_e_ceo_id_eea7b8_idx')],
|
'indexes': [models.Index(fields=['ceo_id'], name='eveonline_e_ceo_id_eea7b8_idx')],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EveCharacter',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('character_id', models.PositiveIntegerField(unique=True)),
|
||||||
|
('character_name', models.CharField(db_index=True, max_length=254)),
|
||||||
|
('corporation_id', models.PositiveIntegerField()),
|
||||||
|
('corporation_name', models.CharField(max_length=254)),
|
||||||
|
('corporation_ticker', models.CharField(max_length=5)),
|
||||||
|
('alliance_id', models.PositiveIntegerField(blank=True, default=None, null=True)),
|
||||||
|
('alliance_name', models.CharField(blank=True, default='', max_length=254)),
|
||||||
|
('alliance_ticker', models.CharField(blank=True, default='', max_length=5)),
|
||||||
|
('faction_id', models.PositiveIntegerField(blank=True, default=None, null=True)),
|
||||||
|
('faction_name', models.CharField(blank=True, default='', max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'indexes': [models.Index(fields=['corporation_id'], name='eveonline_e_corpora_cb4cd9_idx'), models.Index(fields=['alliance_id'], name='eveonline_e_allianc_39ee2a_idx'), models.Index(fields=['corporation_name'], name='eveonline_e_corpora_893c60_idx'), models.Index(fields=['alliance_name'], name='eveonline_e_allianc_63fd98_idx'), models.Index(fields=['faction_id'], name='eveonline_e_faction_d5274e_idx')],
|
||||||
|
},
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -32,7 +32,7 @@ class EveFactionInfo(models.Model):
|
|||||||
|
|
||||||
provider = providers.provider
|
provider = providers.provider
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.faction_name
|
return self.faction_name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -80,9 +80,11 @@ class EveAllianceInfo(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
indexes = [models.Index(fields=['executor_corp_id',])]
|
indexes = [models.Index(fields=['executor_corp_id',])]
|
||||||
def __str__(self):
|
|
||||||
|
def __str__(self) -> str:
|
||||||
return self.alliance_name
|
return self.alliance_name
|
||||||
def populate_alliance(self):
|
|
||||||
|
def populate_alliance(self) -> None:
|
||||||
alliance = self.provider.get_alliance(self.alliance_id)
|
alliance = self.provider.get_alliance(self.alliance_id)
|
||||||
for corp_id in alliance.corp_ids:
|
for corp_id in alliance.corp_ids:
|
||||||
if not EveCorporationInfo.objects.filter(corporation_id=corp_id).exists():
|
if not EveCorporationInfo.objects.filter(corporation_id=corp_id).exists():
|
||||||
@ -101,8 +103,6 @@ class EveAllianceInfo(models.Model):
|
|||||||
self.save()
|
self.save()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generic_logo_url(
|
def generic_logo_url(
|
||||||
alliance_id: int, size: int = _DEFAULT_IMAGE_SIZE
|
alliance_id: int, size: int = _DEFAULT_IMAGE_SIZE
|
||||||
@ -152,8 +152,10 @@ class EveCorporationInfo(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
indexes = [models.Index(fields=['ceo_id',]),]
|
indexes = [models.Index(fields=['ceo_id',]),]
|
||||||
def __str__(self):
|
|
||||||
|
def __str__(self) -> str:
|
||||||
return self.corporation_name
|
return self.corporation_name
|
||||||
|
|
||||||
def update_corporation(self, corp: providers.Corporation = None):
|
def update_corporation(self, corp: providers.Corporation = None):
|
||||||
if corp is None:
|
if corp is None:
|
||||||
corp = self.provider.get_corporation(self.corporation_id)
|
corp = self.provider.get_corporation(self.corporation_id)
|
||||||
@ -166,8 +168,6 @@ class EveCorporationInfo(models.Model):
|
|||||||
self.save()
|
self.save()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generic_logo_url(
|
def generic_logo_url(
|
||||||
corporation_id: int, size: int = _DEFAULT_IMAGE_SIZE
|
corporation_id: int, size: int = _DEFAULT_IMAGE_SIZE
|
||||||
@ -226,7 +226,7 @@ class EveCharacter(models.Model):
|
|||||||
models.Index(fields=['faction_id',]),
|
models.Index(fields=['faction_id',]),
|
||||||
]
|
]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.character_name
|
return self.character_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
from bravado.exception import HTTPError, HTTPNotFound, HTTPUnprocessableEntity
|
from bravado.exception import HTTPError, HTTPNotFound, HTTPUnprocessableEntity
|
||||||
from jsonschema.exceptions import RefResolutionError
|
from jsonschema.exceptions import RefResolutionError
|
||||||
@ -36,7 +37,7 @@ class ObjectNotFound(Exception):
|
|||||||
self.id = obj_id
|
self.id = obj_id
|
||||||
self.type = type_name
|
self.type = type_name
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f'{self.type} with ID {self.id} not found.'
|
return f'{self.type} with ID {self.id} not found.'
|
||||||
|
|
||||||
|
|
||||||
@ -46,13 +47,13 @@ class Entity:
|
|||||||
self.id = id
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f"<{self.__class__.__name__} ({self.id}): {self.name}>"
|
return f"<{self.__class__.__name__} ({self.id}): {self.name}>"
|
||||||
|
|
||||||
def __bool__(self):
|
def __bool__(self) -> bool:
|
||||||
return bool(self.id)
|
return bool(self.id)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
@ -206,7 +207,7 @@ class EveSwaggerProvider(EveProvider):
|
|||||||
)
|
)
|
||||||
return self._client
|
return self._client
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> Literal['esi']:
|
||||||
return 'esi'
|
return 'esi'
|
||||||
|
|
||||||
def get_alliance(self, alliance_id: int) -> Alliance:
|
def get_alliance(self, alliance_id: int) -> Alliance:
|
||||||
|
@ -13,7 +13,7 @@ class BravadoResponseStub:
|
|||||||
self.headers = headers if headers else {}
|
self.headers = headers if headers else {}
|
||||||
self.raw_bytes = raw_bytes
|
self.raw_bytes = raw_bytes
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f"{self.status_code} {self.reason}"
|
return f"{self.status_code} {self.reason}"
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class Fatlink(models.Model):
|
|||||||
hash = models.CharField(max_length=254, unique=True)
|
hash = models.CharField(max_length=254, unique=True)
|
||||||
creator = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))
|
creator = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.fleet
|
return self.fleet
|
||||||
|
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ class Fat(models.Model):
|
|||||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (('character', 'fatlink'),)
|
unique_together = (("character", "fatlink"),)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f"Fat-link for {self.character.character_name}"
|
return f"Fat-link for {self.character.character_name}"
|
||||||
|
@ -15,7 +15,7 @@ class GroupRequest(models.Model):
|
|||||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
group = models.ForeignKey(Group, on_delete=models.CASCADE)
|
group = models.ForeignKey(Group, on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.user.username + ":" + self.group.name
|
return self.user.username + ":" + self.group.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -50,10 +50,10 @@ class RequestLog(models.Model):
|
|||||||
request_actor = models.ForeignKey(User, on_delete=models.CASCADE)
|
request_actor = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
date = models.DateTimeField(auto_now_add=True)
|
date = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.pk
|
return self.pk
|
||||||
|
|
||||||
def requestor(self):
|
def requestor(self) -> str:
|
||||||
return self.request_info.split(":")[0]
|
return self.request_info.split(":")[0]
|
||||||
|
|
||||||
def type_to_str(self):
|
def type_to_str(self):
|
||||||
@ -182,7 +182,7 @@ class AuthGroup(models.Model):
|
|||||||
)
|
)
|
||||||
default_permissions = ()
|
default_permissions = ()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.group.name
|
return self.group.name
|
||||||
|
|
||||||
def group_request_approvers(self) -> set[User]:
|
def group_request_approvers(self) -> set[User]:
|
||||||
|
@ -13,7 +13,7 @@ class ApplicationQuestion(models.Model):
|
|||||||
help_text = models.CharField(max_length=254, blank=True)
|
help_text = models.CharField(max_length=254, blank=True)
|
||||||
multi_select = models.BooleanField(default=False)
|
multi_select = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return "Question: " + self.title
|
return "Question: " + self.title
|
||||||
|
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ class ApplicationChoice(models.Model):
|
|||||||
question = models.ForeignKey(ApplicationQuestion,on_delete=models.CASCADE,related_name="choices")
|
question = models.ForeignKey(ApplicationQuestion,on_delete=models.CASCADE,related_name="choices")
|
||||||
choice_text = models.CharField(max_length=200, verbose_name='Choice')
|
choice_text = models.CharField(max_length=200, verbose_name='Choice')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.choice_text
|
return self.choice_text
|
||||||
|
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ class ApplicationForm(models.Model):
|
|||||||
questions = SortedManyToManyField(ApplicationQuestion)
|
questions = SortedManyToManyField(ApplicationQuestion)
|
||||||
corp = models.OneToOneField(EveCorporationInfo, on_delete=models.CASCADE)
|
corp = models.OneToOneField(EveCorporationInfo, on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return str(self.corp)
|
return str(self.corp)
|
||||||
|
|
||||||
|
|
||||||
@ -43,14 +43,13 @@ class Application(models.Model):
|
|||||||
|
|
||||||
objects = ApplicationManager()
|
objects = ApplicationManager()
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
('approve_application', 'Can approve applications'), ('reject_application', 'Can reject applications'),
|
('approve_application', 'Can approve applications'), ('reject_application', 'Can reject applications'),
|
||||||
('view_apis', 'Can view applicant APIs'),)
|
('view_apis', 'Can view applicant APIs'),)
|
||||||
unique_together = ('form', 'user')
|
unique_together = ('form', 'user')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return str(self.user) + " Application To " + str(self.form)
|
return str(self.user) + " Application To " + str(self.form)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -75,19 +74,19 @@ class ApplicationResponse(models.Model):
|
|||||||
question = models.ForeignKey(ApplicationQuestion, on_delete=models.CASCADE)
|
question = models.ForeignKey(ApplicationQuestion, on_delete=models.CASCADE)
|
||||||
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='responses')
|
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='responses')
|
||||||
answer = models.TextField()
|
answer = models.TextField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('question', 'application')
|
unique_together = ('question', 'application')
|
||||||
def __str__(self):
|
|
||||||
|
def __str__(self) -> str:
|
||||||
return str(self.application) + " Answer To " + str(self.question)
|
return str(self.application) + " Answer To " + str(self.question)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ApplicationComment(models.Model):
|
class ApplicationComment(models.Model):
|
||||||
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='comments')
|
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='comments')
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
text = models.TextField()
|
text = models.TextField()
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return str(self.user) + " comment on " + str(self.application)
|
return str(self.user) + " comment on " + str(self.application)
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('menu', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='menuitem',
|
||||||
|
name='hook_hash',
|
||||||
|
field=models.CharField(default=None, editable=False, help_text='hash of a menu item hook. Must be nullable for unique comparison.', max_length=64, null=True, unique=True),
|
||||||
|
),
|
||||||
|
]
|
@ -40,10 +40,7 @@ class MenuItem(models.Model):
|
|||||||
is_hidden = models.BooleanField(
|
is_hidden = models.BooleanField(
|
||||||
default=False,
|
default=False,
|
||||||
verbose_name=_("is hidden"),
|
verbose_name=_("is hidden"),
|
||||||
help_text=_(
|
help_text=_("Hide this menu item." "If this item is a folder all items under it will be hidden too"),
|
||||||
"Hide this menu item."
|
|
||||||
"If this item is a folder all items under it will be hidden too"
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# app related properties
|
# app related properties
|
||||||
@ -53,7 +50,7 @@ class MenuItem(models.Model):
|
|||||||
null=True,
|
null=True,
|
||||||
unique=True,
|
unique=True,
|
||||||
editable=False,
|
editable=False,
|
||||||
help_text="hash of a menu item hook. Must be nullable for unique comparison."
|
help_text="hash of a menu item hook. Must be nullable for unique comparison.",
|
||||||
)
|
)
|
||||||
|
|
||||||
# user defined properties
|
# user defined properties
|
||||||
@ -62,10 +59,7 @@ class MenuItem(models.Model):
|
|||||||
default="",
|
default="",
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name=_("icon classes"),
|
verbose_name=_("icon classes"),
|
||||||
help_text=_(
|
help_text=_("Font Awesome classes to show as icon on menu, " "e.g. <code>fa-solid fa-house</code>"),
|
||||||
"Font Awesome classes to show as icon on menu, "
|
|
||||||
"e.g. <code>fa-solid fa-house</code>"
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
url = models.TextField(
|
url = models.TextField(
|
||||||
default="",
|
default="",
|
||||||
@ -78,7 +72,7 @@ class MenuItem(models.Model):
|
|||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.text
|
return self.text
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs) -> None:
|
||||||
if not self.hook_hash:
|
if not self.hook_hash:
|
||||||
self.hook_hash = None # empty strings can create problems
|
self.hook_hash = None # empty strings can create problems
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
@ -124,14 +118,12 @@ class MenuItem(models.Model):
|
|||||||
if self.is_app_item:
|
if self.is_app_item:
|
||||||
raise ValueError("The related hook objects should be used for app items.")
|
raise ValueError("The related hook objects should be used for app items.")
|
||||||
|
|
||||||
hook_obj = MenuItemHookCustom(
|
hook_obj = MenuItemHookCustom(text=self.text, classes=self.classes, url_name="", order=self.order)
|
||||||
text=self.text, classes=self.classes, url_name="", order=self.order
|
|
||||||
)
|
|
||||||
hook_obj.navactive = []
|
hook_obj.navactive = []
|
||||||
if self.is_folder and not self.classes:
|
if self.is_folder and not self.classes:
|
||||||
hook_obj.classes = DEFAULT_FOLDER_ICON_CLASSES
|
hook_obj.classes = DEFAULT_FOLDER_ICON_CLASSES
|
||||||
|
|
||||||
hook_obj.url = self.url
|
hook_obj.url = self.url
|
||||||
hook_obj.is_folder = self.is_folder
|
hook_obj.is_folder = self.is_folder
|
||||||
hook_obj.html_id = f"id-folder-{self.id}" if self.is_folder else ""
|
hook_obj.html_id = f"id-folder-{self.pk}" if self.is_folder else ""
|
||||||
return hook_obj
|
return hook_obj
|
||||||
|
@ -61,12 +61,12 @@ class Notification(models.Model):
|
|||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"{self.user}: {self.title}"
|
return f"{self.user}: {self.title}"
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs) -> None:
|
||||||
# overriden save to ensure cache is invaidated on very call
|
# overriden save to ensure cache is invaidated on very call
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs) -> None:
|
||||||
# overriden delete to ensure cache is invaidated on very call
|
# overriden delete to ensure cache is invaidated on very call
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
||||||
|
@ -7,24 +7,17 @@ from allianceauth.eveonline.models import EveCharacter
|
|||||||
|
|
||||||
|
|
||||||
class OpTimerType(models.Model):
|
class OpTimerType(models.Model):
|
||||||
"""
|
|
||||||
Optimer Type
|
|
||||||
"""
|
|
||||||
|
|
||||||
type = models.CharField(max_length=254, default="")
|
type = models.CharField(max_length=254, default="")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['type']
|
ordering = ["type"]
|
||||||
default_permissions = ()
|
default_permissions = ()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.type
|
return self.type
|
||||||
|
|
||||||
|
|
||||||
class OpTimer(models.Model):
|
class OpTimer(models.Model):
|
||||||
|
|
||||||
|
|
||||||
doctrine = models.CharField(max_length=254, default="")
|
doctrine = models.CharField(max_length=254, default="")
|
||||||
system = models.CharField(max_length=254, default="")
|
system = models.CharField(max_length=254, default="")
|
||||||
start = models.DateTimeField(default=datetime.now)
|
start = models.DateTimeField(default=datetime.now)
|
||||||
@ -32,12 +25,13 @@ class OpTimer(models.Model):
|
|||||||
operation_name = models.CharField(max_length=254, default="")
|
operation_name = models.CharField(max_length=254, default="")
|
||||||
fc = models.CharField(max_length=254, default="")
|
fc = models.CharField(max_length=254, default="")
|
||||||
post_time = models.DateTimeField(default=timezone.now)
|
post_time = models.DateTimeField(default=timezone.now)
|
||||||
eve_character = models.ForeignKey(EveCharacter, null=True,
|
eve_character = models.ForeignKey(EveCharacter, null=True, on_delete=models.SET_NULL)
|
||||||
on_delete=models.SET_NULL)
|
|
||||||
description = models.TextField(blank=True, default="")
|
description = models.TextField(blank=True, default="")
|
||||||
type = models.ForeignKey(OpTimerType, null=True, on_delete=models.SET_NULL)
|
type = models.ForeignKey(OpTimerType, null=True, on_delete=models.SET_NULL)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['start']
|
ordering = ["start"]
|
||||||
default_permissions = ()
|
default_permissions = ()
|
||||||
def __str__(self):
|
|
||||||
|
def __str__(self) -> str:
|
||||||
return self.operation_name
|
return self.operation_name
|
||||||
|
@ -5,11 +5,10 @@ class PermissionsTool(models.Model):
|
|||||||
"""
|
"""
|
||||||
Dummy model for holding permissions
|
Dummy model for holding permissions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
managed = False
|
managed = False
|
||||||
permissions = (
|
permissions = (("audit_permissions", "Can audit permissions"),)
|
||||||
('audit_permissions', 'Can audit permissions'),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"{self.pk}"
|
return f"{self.pk}"
|
||||||
|
@ -119,7 +119,7 @@ class ServicesHook:
|
|||||||
"""
|
"""
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.name or 'Unknown Service Module'
|
return self.name or 'Unknown Service Module'
|
||||||
|
|
||||||
class Urls:
|
class Urls:
|
||||||
|
@ -6,8 +6,6 @@ from django.db import migrations
|
|||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
replaces = [('services', '0001_initial'), ('services', '0002_auto_20161016_0135'), ('services', '0003_delete_groupcache')]
|
|
||||||
|
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
29
allianceauth/services/migrations/0004_v5squash.py
Normal file
29
allianceauth/services/migrations/0004_v5squash.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:12
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('services', '0001_squashed_0003_delete_groupcache'), ('services', '0002_nameformatter'), ('services', '0003_remove_broken_link')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('authentication', '0025_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='NameFormatConfig',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('service_name', models.CharField(max_length=100)),
|
||||||
|
('default_to_username', models.BooleanField(default=True, help_text='If a user has no main_character, default to using their Auth username instead.')),
|
||||||
|
('format', models.CharField(help_text='For information on constructing name formats please see the official documentation, topic "Services Name Formats".', max_length=100)),
|
||||||
|
('states', models.ManyToManyField(help_text='States to apply this format to. You should only have one formatter for each state for each service.', to='authentication.state')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
@ -26,7 +26,7 @@ class NameFormatConfig(models.Model):
|
|||||||
"formatter for each state for each service."
|
"formatter for each state for each service."
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return '{}: {}'.format(
|
return '{}: {}'.format(
|
||||||
self.service_name, ', '.join([str(x) for x in self.states.all()])
|
self.service_name, ', '.join([str(x) for x in self.states.all()])
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:18
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('discord', '0001_initial'), ('discord', '0002_service_permissions'), ('discord', '0003_big_overhaul')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='DiscordUser',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(help_text='Auth user owning this Discord account', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='discord', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('uid', models.BigIntegerField(db_index=True, help_text="user's ID on Discord")),
|
||||||
|
('activated', models.DateTimeField(blank=True, default=None, help_text='Date & time this service account was activated', null=True)),
|
||||||
|
('discriminator', models.CharField(blank=True, default='', help_text="user's discriminator on Discord", max_length=4)),
|
||||||
|
('username', models.CharField(blank=True, db_index=True, default='', help_text="user's username on Discord", max_length=32)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_discord', 'Can access the Discord service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -25,45 +25,28 @@ class DiscordUser(models.Model):
|
|||||||
User,
|
User,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='discord',
|
related_name="discord",
|
||||||
help_text='Auth user owning this Discord account'
|
help_text="Auth user owning this Discord account",
|
||||||
)
|
|
||||||
uid = models.BigIntegerField(
|
|
||||||
db_index=True,
|
|
||||||
help_text='user\'s ID on Discord'
|
|
||||||
)
|
)
|
||||||
|
uid = models.BigIntegerField(db_index=True, help_text="user's ID on Discord")
|
||||||
username = models.CharField(
|
username = models.CharField(
|
||||||
max_length=32,
|
max_length=32, default="", blank=True, db_index=True, help_text="user's username on Discord"
|
||||||
default='',
|
|
||||||
blank=True,
|
|
||||||
db_index=True,
|
|
||||||
help_text='user\'s username on Discord'
|
|
||||||
)
|
|
||||||
discriminator = models.CharField(
|
|
||||||
max_length=4,
|
|
||||||
default='',
|
|
||||||
blank=True,
|
|
||||||
help_text='user\'s discriminator on Discord'
|
|
||||||
)
|
)
|
||||||
|
discriminator = models.CharField(max_length=4, default="", blank=True, help_text="user's discriminator on Discord")
|
||||||
activated = models.DateTimeField(
|
activated = models.DateTimeField(
|
||||||
default=None,
|
default=None, null=True, blank=True, help_text="Date & time this service account was activated"
|
||||||
null=True,
|
|
||||||
blank=True,
|
|
||||||
help_text='Date & time this service account was activated'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = DiscordUserManager()
|
objects = DiscordUserManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("access_discord", "Can access the Discord service"),)
|
||||||
("access_discord", "Can access the Discord service"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f'{self.user.username} - {self.uid}'
|
return f"{self.user.username} - {self.uid}"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f'{type(self).__name__}(user=\'{self.user}\', uid={self.uid})'
|
return f"{type(self).__name__}(user='{self.user}', uid={self.uid})"
|
||||||
|
|
||||||
def update_nickname(self, nickname: str = None) -> bool:
|
def update_nickname(self, nickname: str = None) -> bool:
|
||||||
"""Update nickname with formatted name of main character
|
"""Update nickname with formatted name of main character
|
||||||
@ -80,15 +63,11 @@ class DiscordUser(models.Model):
|
|||||||
nickname = user_formatted_nick(self.user)
|
nickname = user_formatted_nick(self.user)
|
||||||
if not nickname:
|
if not nickname:
|
||||||
return False
|
return False
|
||||||
success = default_bot_client.modify_guild_member(
|
success = default_bot_client.modify_guild_member(guild_id=DISCORD_GUILD_ID, user_id=self.uid, nick=nickname)
|
||||||
guild_id=DISCORD_GUILD_ID,
|
|
||||||
user_id=self.uid,
|
|
||||||
nick=nickname
|
|
||||||
)
|
|
||||||
if success:
|
if success:
|
||||||
logger.info('Nickname for %s has been updated', self.user)
|
logger.info("Nickname for %s has been updated", self.user)
|
||||||
else:
|
else:
|
||||||
logger.warning('Failed to update nickname for %s', self.user)
|
logger.warning("Failed to update nickname for %s", self.user)
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def update_groups(self, state_name: str = None) -> bool | None:
|
def update_groups(self, state_name: str = None) -> bool | None:
|
||||||
@ -104,27 +83,22 @@ class DiscordUser(models.Model):
|
|||||||
- False on error or raises exception
|
- False on error or raises exception
|
||||||
"""
|
"""
|
||||||
new_roles, is_changed = calculate_roles_for_user(
|
new_roles, is_changed = calculate_roles_for_user(
|
||||||
user=self.user,
|
user=self.user, client=default_bot_client, discord_uid=self.uid, state_name=state_name
|
||||||
client=default_bot_client,
|
|
||||||
discord_uid=self.uid,
|
|
||||||
state_name=state_name
|
|
||||||
)
|
)
|
||||||
if is_changed is None:
|
if is_changed is None:
|
||||||
logger.debug('User is not a member of this guild %s', self.user)
|
logger.debug("User is not a member of this guild %s", self.user)
|
||||||
return None
|
return None
|
||||||
if is_changed:
|
if is_changed:
|
||||||
logger.debug('Need to update roles for user %s', self.user)
|
logger.debug("Need to update roles for user %s", self.user)
|
||||||
success = default_bot_client.modify_guild_member(
|
success = default_bot_client.modify_guild_member(
|
||||||
guild_id=DISCORD_GUILD_ID,
|
guild_id=DISCORD_GUILD_ID, user_id=self.uid, role_ids=list(new_roles.ids())
|
||||||
user_id=self.uid,
|
|
||||||
role_ids=list(new_roles.ids())
|
|
||||||
)
|
)
|
||||||
if success:
|
if success:
|
||||||
logger.info('Roles for %s have been updated', self.user)
|
logger.info("Roles for %s have been updated", self.user)
|
||||||
else:
|
else:
|
||||||
logger.warning('Failed to update roles for %s', self.user)
|
logger.warning("Failed to update roles for %s", self.user)
|
||||||
return success
|
return success
|
||||||
logger.info('No need to update roles for user %s', self.user)
|
logger.info("No need to update roles for user %s", self.user)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_username(self) -> bool | None:
|
def update_username(self) -> bool | None:
|
||||||
@ -135,23 +109,18 @@ class DiscordUser(models.Model):
|
|||||||
- True on success
|
- True on success
|
||||||
- None if user is no longer a member of the Discord server
|
- None if user is no longer a member of the Discord server
|
||||||
"""
|
"""
|
||||||
member_info = default_bot_client.guild_member(
|
member_info = default_bot_client.guild_member(guild_id=DISCORD_GUILD_ID, user_id=self.uid)
|
||||||
guild_id=DISCORD_GUILD_ID, user_id=self.uid
|
|
||||||
)
|
|
||||||
if not member_info:
|
if not member_info:
|
||||||
logger.warning('%s: User not a guild member', self.user)
|
logger.warning("%s: User not a guild member", self.user)
|
||||||
return None
|
return None
|
||||||
self.username = member_info.user.username
|
self.username = member_info.user.username
|
||||||
self.discriminator = member_info.user.discriminator
|
self.discriminator = member_info.user.discriminator
|
||||||
self.save()
|
self.save()
|
||||||
logger.info('%s: Username has been updated', self.user)
|
logger.info("%s: Username has been updated", self.user)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def delete_user(
|
def delete_user(
|
||||||
self,
|
self, notify_user: bool = False, is_rate_limited: bool = True, handle_api_exceptions: bool = False
|
||||||
notify_user: bool = False,
|
|
||||||
is_rate_limited: bool = True,
|
|
||||||
handle_api_exceptions: bool = False
|
|
||||||
) -> bool | None:
|
) -> bool | None:
|
||||||
"""Deletes the Discount user both on the server and locally
|
"""Deletes the Discount user both on the server and locally
|
||||||
|
|
||||||
@ -168,37 +137,31 @@ class DiscordUser(models.Model):
|
|||||||
try:
|
try:
|
||||||
_user = self.user
|
_user = self.user
|
||||||
client = create_bot_client(is_rate_limited=is_rate_limited)
|
client = create_bot_client(is_rate_limited=is_rate_limited)
|
||||||
success = client.remove_guild_member(
|
success = client.remove_guild_member(guild_id=DISCORD_GUILD_ID, user_id=self.uid)
|
||||||
guild_id=DISCORD_GUILD_ID, user_id=self.uid
|
|
||||||
)
|
|
||||||
if success is not False:
|
if success is not False:
|
||||||
deleted_count, _ = self.delete()
|
deleted_count, _ = self.delete()
|
||||||
if deleted_count > 0:
|
if deleted_count > 0:
|
||||||
if notify_user:
|
if notify_user:
|
||||||
notify(
|
notify(
|
||||||
user=_user,
|
user=_user,
|
||||||
title=gettext_lazy('Discord Account Disabled'),
|
title=gettext_lazy("Discord Account Disabled"),
|
||||||
message=gettext_lazy(
|
message=gettext_lazy(
|
||||||
'Your Discord account was disabled automatically '
|
"Your Discord account was disabled automatically "
|
||||||
'by Auth. If you think this was a mistake, '
|
"by Auth. If you think this was a mistake, "
|
||||||
'please contact an admin.'
|
"please contact an admin."
|
||||||
),
|
),
|
||||||
level='warning'
|
level="warning",
|
||||||
)
|
)
|
||||||
logger.info('Account for user %s was deleted.', _user)
|
logger.info("Account for user %s was deleted.", _user)
|
||||||
return True
|
return True
|
||||||
logger.debug('Account for user %s was already deleted.', _user)
|
logger.debug("Account for user %s was already deleted.", _user)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
logger.warning(
|
logger.warning("Failed to remove user %s from the Discord server", _user)
|
||||||
'Failed to remove user %s from the Discord server', _user
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except (HTTPError, ConnectionError, DiscordApiBackoff) as ex:
|
except (HTTPError, ConnectionError, DiscordApiBackoff) as ex:
|
||||||
if handle_api_exceptions:
|
if handle_api_exceptions:
|
||||||
logger.exception(
|
logger.exception("Failed to remove user %s from Discord server: %s", self.user, ex)
|
||||||
'Failed to remove user %s from Discord server: %s',self.user, ex
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
raise ex
|
raise ex
|
||||||
|
@ -17,7 +17,7 @@ class DiscourseError(Exception):
|
|||||||
self.endpoint = endpoint
|
self.endpoint = endpoint
|
||||||
self.errors = errors
|
self.errors = errors
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f"API execution failed.\nErrors: {self.errors}\nEndpoint: {self.endpoint}"
|
return f"API execution failed.\nErrors: {self.errors}\nEndpoint: {self.endpoint}"
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:23
|
||||||
|
|
||||||
|
import django.db.migrations.operations.special
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('discourse', '0001_initial'), ('discourse', '0002_service_permissions')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='DiscourseUser',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='discourse', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('enabled', models.BooleanField()),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_discourse', 'Can access the Discourse service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -3,18 +3,11 @@ from django.db import models
|
|||||||
|
|
||||||
|
|
||||||
class DiscourseUser(models.Model):
|
class DiscourseUser(models.Model):
|
||||||
user = models.OneToOneField(User,
|
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE, related_name="discourse")
|
||||||
primary_key=True,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='discourse')
|
|
||||||
enabled = models.BooleanField()
|
enabled = models.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("access_discourse", "Can access the Discourse service"),)
|
||||||
("access_discourse", "Can access the Discourse service"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.user.username
|
return self.user.username
|
||||||
|
@ -9,5 +9,5 @@ class ExampleUser(models.Model):
|
|||||||
related_name='example')
|
related_name='example')
|
||||||
username = models.CharField(max_length=254)
|
username = models.CharField(max_length=254)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:24
|
||||||
|
|
||||||
|
import django.db.migrations.operations.special
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
# Functions from the following migrations need manual copying.
|
||||||
|
# Move them and any dependencies into this file, then update the
|
||||||
|
# RunPython operations to refer to the local versions:
|
||||||
|
# allianceauth.services.modules.ips4.migrations.0002_service_permissions
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('ips4', '0001_initial'), ('ips4', '0002_service_permissions')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Ips4User',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='ips4', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('username', models.CharField(max_length=254)),
|
||||||
|
('id', models.CharField(max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_ips4', 'Can access the IPS4 service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -3,18 +3,12 @@ from django.db import models
|
|||||||
|
|
||||||
|
|
||||||
class Ips4User(models.Model):
|
class Ips4User(models.Model):
|
||||||
user = models.OneToOneField(User,
|
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE, related_name="ips4")
|
||||||
primary_key=True,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='ips4')
|
|
||||||
username = models.CharField(max_length=254)
|
username = models.CharField(max_length=254)
|
||||||
id = models.CharField(max_length=254)
|
id = models.CharField(max_length=254)
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("access_ips4", "Can access the IPS4 service"),)
|
||||||
("access_ips4", "Can access the IPS4 service"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
# Generated by Django 1.10.2 on 2016-12-12 00:58
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='MumbleUser',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('username', models.CharField(max_length=254, unique=True)),
|
|
||||||
('pwhash', models.CharField(max_length=40)),
|
|
||||||
('groups', models.TextField(blank=True, null=True)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'db_table': 'services_mumbleuser',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
@ -8,8 +8,6 @@ from django.db import migrations, models
|
|||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
replaces = [('mumble', '0001_initial'), ('mumble', '0002_auto_20161212_0100'), ('mumble', '0003_mumbleuser_user'), ('mumble', '0004_auto_20161214_1024'), ('mumble', '0005_mumbleuser_hashfn'), ('mumble', '0006_service_permissions'), ('mumble', '0007_not_null_user'), ('mumble', '0008_mumbleuser_display_name'), ('mumble', '0009_set_mumble_dissplay_names'), ('mumble', '0010_mumbleuser_certhash'), ('mumble', '0011_auto_20201011_1009')]
|
|
||||||
|
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
@ -25,13 +23,6 @@ class Migration(migrations.Migration):
|
|||||||
('pwhash', models.CharField(max_length=40)),
|
('pwhash', models.CharField(max_length=40)),
|
||||||
('groups', models.TextField(blank=True, null=True)),
|
('groups', models.TextField(blank=True, null=True)),
|
||||||
],
|
],
|
||||||
options={
|
|
||||||
'db_table': 'services_mumbleuser',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelTable(
|
|
||||||
name='mumbleuser',
|
|
||||||
table=None,
|
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='mumbleuser',
|
model_name='mumbleuser',
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
# Generated by Django 1.10.2 on 2016-12-12 01:00
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterModelTable(
|
|
||||||
name='mumbleuser',
|
|
||||||
table=None,
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,21 +0,0 @@
|
|||||||
# Generated by Django 1.10.2 on 2016-12-12 03:31
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
('mumble', '0002_auto_20161212_0100'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='user',
|
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mumble', to=settings.AUTH_USER_MODEL),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,20 +0,0 @@
|
|||||||
# Generated by Django 1.10.4 on 2016-12-14 10:24
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0003_mumbleuser_user'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='user',
|
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mumble', to=settings.AUTH_USER_MODEL),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,23 +0,0 @@
|
|||||||
# Generated by Django 1.10.4 on 2017-01-23 10:28
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0004_auto_20161214_1024'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='hashfn',
|
|
||||||
field=models.CharField(default='sha1', max_length=20),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='pwhash',
|
|
||||||
field=models.CharField(max_length=80),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,59 +0,0 @@
|
|||||||
# Generated by Django 1.10.5 on 2017-02-02 05:59
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.contrib.auth.management import create_permissions
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def migrate_service_enabled(apps, schema_editor):
|
|
||||||
for app_config in apps.get_app_configs():
|
|
||||||
app_config.models_module = True
|
|
||||||
create_permissions(app_config, apps=apps, verbosity=0)
|
|
||||||
app_config.models_module = None
|
|
||||||
|
|
||||||
Group = apps.get_model("auth", "Group")
|
|
||||||
Permission = apps.get_model("auth", "Permission")
|
|
||||||
MumbleUser = apps.get_model("mumble", "MumbleUser")
|
|
||||||
|
|
||||||
perm = Permission.objects.get(codename='access_mumble')
|
|
||||||
|
|
||||||
member_group_name = getattr(settings, 'DEFAULT_AUTH_GROUP', 'Member')
|
|
||||||
blue_group_name = getattr(settings, 'DEFAULT_BLUE_GROUP', 'Blue')
|
|
||||||
|
|
||||||
# Migrate members
|
|
||||||
if MumbleUser.objects.filter(user__groups__name=member_group_name).exists() or \
|
|
||||||
getattr(settings, 'ENABLE_AUTH_MUMBLE', False):
|
|
||||||
try:
|
|
||||||
group = Group.objects.get(name=member_group_name)
|
|
||||||
group.permissions.add(perm)
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
logger.warning('Failed to migrate ENABLE_AUTH_MUMBLE setting')
|
|
||||||
|
|
||||||
# Migrate blues
|
|
||||||
if MumbleUser.objects.filter(user__groups__name=blue_group_name).exists() or \
|
|
||||||
getattr(settings, 'ENABLE_BLUE_MUMBLE', False):
|
|
||||||
try:
|
|
||||||
group = Group.objects.get(name=blue_group_name)
|
|
||||||
group.permissions.add(perm)
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
logger.warning('Failed to migrate ENABLE_BLUE_MUMBLE setting')
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0005_mumbleuser_hashfn'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name='mumbleuser',
|
|
||||||
options={'permissions': (('access_mumble', 'Can access the Mumble service'),)},
|
|
||||||
),
|
|
||||||
migrations.RunPython(migrate_service_enabled, migrations.RunPython.noop),
|
|
||||||
]
|
|
@ -1,24 +0,0 @@
|
|||||||
# Generated by Django 1.11.6 on 2017-10-09 09:19
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0006_service_permissions'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='id',
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='user',
|
|
||||||
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='mumble', serialize=False, to=settings.AUTH_USER_MODEL),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 2.2.9 on 2020-03-16 07:49
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0007_not_null_user'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='display_name',
|
|
||||||
field=models.CharField(max_length=254, null=True),
|
|
||||||
)
|
|
||||||
]
|
|
@ -1,40 +0,0 @@
|
|||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
from allianceauth.services.hooks import NameFormatter
|
|
||||||
|
|
||||||
from ..auth_hooks import MumbleService
|
|
||||||
|
|
||||||
|
|
||||||
def fwd_func(apps, schema_editor):
|
|
||||||
MumbleUser = apps.get_model("mumble", "MumbleUser")
|
|
||||||
db_alias = schema_editor.connection.alias
|
|
||||||
all_users = MumbleUser.objects.using(db_alias).all()
|
|
||||||
for user in all_users:
|
|
||||||
display_name = NameFormatter(MumbleService(), user.user).format_name()
|
|
||||||
user.display_name = display_name
|
|
||||||
user.save()
|
|
||||||
|
|
||||||
def rev_func(apps, schema_editor):
|
|
||||||
MumbleUser = apps.get_model("mumble", "MumbleUser")
|
|
||||||
db_alias = schema_editor.connection.alias
|
|
||||||
all_users = MumbleUser.objects.using(db_alias).all()
|
|
||||||
for user in all_users:
|
|
||||||
user.display_name = None
|
|
||||||
user.save()
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0008_mumbleuser_display_name'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RunPython(fwd_func, rev_func),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='display_name',
|
|
||||||
field=models.CharField(max_length=254, unique=True),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 2.2.11 on 2020-05-22 13:02
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0009_set_mumble_dissplay_names'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='certhash',
|
|
||||||
field=models.CharField(blank=True, editable=False, help_text='Hash of Mumble client certificate as presented when user authenticates', max_length=254, null=True, verbose_name='Certificate Hash'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 3.1.2 on 2020-10-11 10:09
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('mumble', '0010_mumbleuser_certhash'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='mumbleuser',
|
|
||||||
name='pwhash',
|
|
||||||
field=models.CharField(max_length=90),
|
|
||||||
),
|
|
||||||
]
|
|
@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:44
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mumble', '0013_connection_history'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='certhash',
|
||||||
|
field=models.CharField(blank=True, default='', editable=False, help_text='Hash of Mumble client certificate as presented when user authenticates', max_length=254, verbose_name='Certificate Hash'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='groups',
|
||||||
|
field=models.TextField(blank=True, default=''),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='release',
|
||||||
|
field=models.TextField(blank=True, default='', editable=False, help_text='Client release. For official releases, this equals the version. For snapshots and git compiles, this will be something else.', max_length=254, verbose_name='Mumble Release'),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,38 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:46
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('mumble', '0001_squashed_0011_auto_20201011_1009'), ('mumble', '0012_mumble_client_info'), ('mumble', '0013_connection_history'), ('mumble', '0014_alter_mumbleuser_certhash_alter_mumbleuser_groups_and_more')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '__first__'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='MumbleUser',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='mumble', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('username', models.CharField(max_length=254, unique=True)),
|
||||||
|
('pwhash', models.CharField(max_length=90)),
|
||||||
|
('groups', models.TextField(blank=True, default='')),
|
||||||
|
('hashfn', models.CharField(default='sha1', max_length=20)),
|
||||||
|
('display_name', models.CharField(max_length=254, unique=True)),
|
||||||
|
('certhash', models.CharField(blank=True, default='', editable=False, help_text='Hash of Mumble client certificate as presented when user authenticates', max_length=254, verbose_name='Certificate Hash')),
|
||||||
|
('last_connect', models.DateTimeField(blank=True, editable=False, help_text='Timestamp of the users Last Connection to Mumble', max_length=254, null=True, verbose_name='Last Connection')),
|
||||||
|
('last_disconnect', models.DateTimeField(blank=True, editable=False, help_text='Timestamp of the users Last Disconnection to Mumble', max_length=254, null=True, verbose_name='Last Disconnection')),
|
||||||
|
('release', models.TextField(blank=True, default='', editable=False, help_text='Client release. For official releases, this equals the version. For snapshots and git compiles, this will be something else.', max_length=254, verbose_name='Mumble Release')),
|
||||||
|
('version', models.IntegerField(blank=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.', null=True, verbose_name='Mumble Version')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_mumble', 'Can access the Mumble service'), ('view_connection_history', 'Can access the connection history of the Mumble service')),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -14,16 +14,17 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class MumbleManager(models.Manager):
|
class MumbleManager(models.Manager):
|
||||||
HASH_FN = 'bcrypt-sha256'
|
HASH_FN = "bcrypt-sha256"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_display_name(user):
|
def get_display_name(user) -> str:
|
||||||
from .auth_hooks import MumbleService
|
from .auth_hooks import MumbleService
|
||||||
|
|
||||||
return NameFormatter(MumbleService(), user).format_name()
|
return NameFormatter(MumbleService(), user).format_name()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_username(user):
|
def get_username(user):
|
||||||
return user.profile.main_character.character_name # main character as the user.username may be incorect
|
return user.profile.main_character.character_name # main character as the user.username may be incorrect
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sanitise_username(username):
|
def sanitise_username(username):
|
||||||
@ -31,11 +32,11 @@ class MumbleManager(models.Manager):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_random_pass():
|
def generate_random_pass():
|
||||||
return ''.join([random.choice(string.ascii_letters + string.digits) for n in range(16)])
|
return "".join([random.choice(string.ascii_letters + string.digits) for n in range(16)])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def gen_pwhash(password):
|
def gen_pwhash(password):
|
||||||
return bcrypt_sha256.encrypt(password.encode('utf-8'))
|
return bcrypt_sha256.encrypt(password.encode("utf-8"))
|
||||||
|
|
||||||
def create(self, user):
|
def create(self, user):
|
||||||
try:
|
try:
|
||||||
@ -45,58 +46,54 @@ class MumbleManager(models.Manager):
|
|||||||
display_name = self.get_display_name(user)
|
display_name = self.get_display_name(user)
|
||||||
password = self.generate_random_pass()
|
password = self.generate_random_pass()
|
||||||
pwhash = self.gen_pwhash(password)
|
pwhash = self.gen_pwhash(password)
|
||||||
logger.debug(f"Proceeding with mumble user creation: clean username {username_clean}, pwhash starts with {pwhash[0:5]}")
|
logger.debug(
|
||||||
|
f"Proceeding with mumble user creation: clean username {username_clean}, pwhash starts with {pwhash[0:5]}"
|
||||||
|
)
|
||||||
logger.info(f"Creating mumble user {username_clean}")
|
logger.info(f"Creating mumble user {username_clean}")
|
||||||
|
|
||||||
result = super().create(user=user, username=username_clean,
|
result = super().create(
|
||||||
pwhash=pwhash, hashfn=self.HASH_FN,
|
user=user, username=username_clean, pwhash=pwhash, hashfn=self.HASH_FN, display_name=display_name
|
||||||
display_name=display_name)
|
)
|
||||||
result.update_groups()
|
result.update_groups()
|
||||||
result.credentials.update({'username': result.username, 'password': password})
|
result.credentials.update({"username": result.username, "password": password})
|
||||||
return result
|
return result
|
||||||
except AttributeError: # No Main or similar errors
|
except AttributeError: # No Main or similar errors
|
||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def user_exists(self, username):
|
def user_exists(self, username) -> bool:
|
||||||
return self.filter(username=username).exists()
|
return self.filter(username=username).exists()
|
||||||
|
|
||||||
|
|
||||||
class MumbleUser(AbstractServiceModel):
|
class MumbleUser(AbstractServiceModel):
|
||||||
user = models.OneToOneField(
|
user = models.OneToOneField("auth.User", primary_key=True, on_delete=models.CASCADE, related_name="mumble")
|
||||||
'auth.User',
|
|
||||||
primary_key=True,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='mumble'
|
|
||||||
)
|
|
||||||
username = models.CharField(max_length=254, unique=True)
|
username = models.CharField(max_length=254, unique=True)
|
||||||
pwhash = models.CharField(max_length=90)
|
pwhash = models.CharField(max_length=90)
|
||||||
hashfn = models.CharField(max_length=20, default='sha1')
|
hashfn = models.CharField(max_length=20, default="sha1")
|
||||||
groups = models.TextField(blank=True)
|
groups = models.TextField(blank=True, default="")
|
||||||
certhash = models.CharField(
|
certhash = models.CharField(
|
||||||
verbose_name="Certificate Hash",
|
verbose_name="Certificate Hash",
|
||||||
max_length=254,
|
max_length=254,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
default="",
|
||||||
editable=False,
|
editable=False,
|
||||||
help_text="Hash of Mumble client certificate as presented when user authenticates"
|
help_text="Hash of Mumble client certificate as presented when user authenticates",
|
||||||
)
|
|
||||||
display_name = models.CharField(
|
|
||||||
max_length=254,
|
|
||||||
unique=True
|
|
||||||
)
|
)
|
||||||
|
display_name = models.CharField(max_length=254, unique=True)
|
||||||
release = models.TextField(
|
release = models.TextField(
|
||||||
verbose_name="Mumble Release",
|
verbose_name="Mumble Release",
|
||||||
max_length=254,
|
max_length=254,
|
||||||
blank=True,
|
blank=True,
|
||||||
editable=False,
|
editable=False,
|
||||||
help_text="Client release. For official releases, this equals the version. For snapshots and git compiles, this will be something else."
|
default="",
|
||||||
|
help_text="Client release. For official releases, this equals the version. For snapshots and git compiles, this will be something else.",
|
||||||
)
|
)
|
||||||
version = models.IntegerField(
|
version = models.IntegerField(
|
||||||
verbose_name="Mumble Version",
|
verbose_name="Mumble Version",
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
editable=False,
|
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."
|
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(
|
last_connect = models.DateTimeField(
|
||||||
verbose_name="Last Connection",
|
verbose_name="Last Connection",
|
||||||
@ -104,7 +101,7 @@ class MumbleUser(AbstractServiceModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
editable=False,
|
editable=False,
|
||||||
help_text="Timestamp of the users Last Connection to Mumble"
|
help_text="Timestamp of the users Last Connection to Mumble",
|
||||||
)
|
)
|
||||||
last_disconnect = models.DateTimeField(
|
last_disconnect = models.DateTimeField(
|
||||||
verbose_name="Last Disconnection",
|
verbose_name="Last Disconnection",
|
||||||
@ -112,15 +109,15 @@ class MumbleUser(AbstractServiceModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
editable=False,
|
editable=False,
|
||||||
help_text="Timestamp of the users Last Disconnection to Mumble"
|
help_text="Timestamp of the users Last Disconnection to Mumble",
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = MumbleManager()
|
objects = MumbleManager()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
|
||||||
def update_password(self, password=None):
|
def update_password(self, password=None) -> None:
|
||||||
init_password = password
|
init_password = password
|
||||||
logger.debug("Updating mumble user %s password.")
|
logger.debug("Updating mumble user %s password.")
|
||||||
if not password:
|
if not password:
|
||||||
@ -131,9 +128,9 @@ class MumbleUser(AbstractServiceModel):
|
|||||||
self.hashfn = MumbleManager.HASH_FN
|
self.hashfn = MumbleManager.HASH_FN
|
||||||
self.save()
|
self.save()
|
||||||
if init_password is None:
|
if init_password is None:
|
||||||
self.credentials.update({'username': self.username, 'password': password})
|
self.credentials.update({"username": self.username, "password": password})
|
||||||
|
|
||||||
def reset_password(self):
|
def reset_password(self) -> None:
|
||||||
self.update_password()
|
self.update_password()
|
||||||
|
|
||||||
def update_groups(self, groups: Group = None):
|
def update_groups(self, groups: Group = None):
|
||||||
@ -142,7 +139,7 @@ class MumbleUser(AbstractServiceModel):
|
|||||||
groups_str = [self.user.profile.state.name]
|
groups_str = [self.user.profile.state.name]
|
||||||
for group in groups:
|
for group in groups:
|
||||||
groups_str.append(str(group.name))
|
groups_str.append(str(group.name))
|
||||||
safe_groups = ','.join({g.replace(' ', '-') for g in groups_str})
|
safe_groups = ",".join({g.replace(" ", "-") for g in groups_str})
|
||||||
logger.info(f"Updating mumble user {self.user} groups to {safe_groups}")
|
logger.info(f"Updating mumble user {self.user} groups to {safe_groups}")
|
||||||
self.groups = safe_groups
|
self.groups = safe_groups
|
||||||
self.save()
|
self.save()
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:48
|
||||||
|
|
||||||
|
import django.db.migrations.operations.special
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
# Functions from the following migrations need manual copying.
|
||||||
|
# Move them and any dependencies into this file, then update the
|
||||||
|
# RunPython operations to refer to the local versions:
|
||||||
|
# allianceauth.services.modules.openfire.migrations.0002_service_permissions
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('openfire', '0001_initial'), ('openfire', '0002_service_permissions')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OpenfireUser',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='openfire', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('username', models.CharField(max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_openfire', 'Can access the Openfire service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -2,17 +2,11 @@ from django.db import models
|
|||||||
|
|
||||||
|
|
||||||
class OpenfireUser(models.Model):
|
class OpenfireUser(models.Model):
|
||||||
user = models.OneToOneField('auth.User',
|
user = models.OneToOneField("auth.User", primary_key=True, on_delete=models.CASCADE, related_name="openfire")
|
||||||
primary_key=True,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='openfire')
|
|
||||||
username = models.CharField(max_length=254)
|
username = models.CharField(max_length=254)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("access_openfire", "Can access the Openfire service"),)
|
||||||
("access_openfire", "Can access the Openfire service"),
|
|
||||||
)
|
def __str__(self) -> str:
|
||||||
def __str__(self):
|
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:50
|
||||||
|
|
||||||
|
import django.db.migrations.operations.special
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
# Functions from the following migrations need manual copying.
|
||||||
|
# Move them and any dependencies into this file, then update the
|
||||||
|
# RunPython operations to refer to the local versions:
|
||||||
|
# allianceauth.services.modules.phpbb3.migrations.0002_service_permissions
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('phpbb3', '0001_initial'), ('phpbb3', '0002_service_permissions')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Phpbb3User',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='phpbb3', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('username', models.CharField(max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_phpbb3', 'Can access the phpBB3 service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -2,16 +2,11 @@ from django.db import models
|
|||||||
|
|
||||||
|
|
||||||
class Phpbb3User(models.Model):
|
class Phpbb3User(models.Model):
|
||||||
user = models.OneToOneField('auth.User',
|
user = models.OneToOneField("auth.User", primary_key=True, on_delete=models.CASCADE, related_name="phpbb3")
|
||||||
primary_key=True,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='phpbb3')
|
|
||||||
username = models.CharField(max_length=254)
|
username = models.CharField(max_length=254)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("access_phpbb3", "Can access the phpBB3 service"),)
|
||||||
("access_phpbb3", "Can access the phpBB3 service"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:51
|
||||||
|
|
||||||
|
import django.db.migrations.operations.special
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
# Functions from the following migrations need manual copying.
|
||||||
|
# Move them and any dependencies into this file, then update the
|
||||||
|
# RunPython operations to refer to the local versions:
|
||||||
|
# allianceauth.services.modules.smf.migrations.0002_service_permissions
|
||||||
|
# allianceauth.services.modules.smf.migrations.0003_set_smf_displayed_names
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('smf', '0001_initial'), ('smf', '0002_service_permissions'), ('smf', '0003_set_smf_displayed_names')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SmfUser',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='smf', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('username', models.CharField(max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_smf', 'Can access the SMF service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -2,16 +2,11 @@ from django.db import models
|
|||||||
|
|
||||||
|
|
||||||
class SmfUser(models.Model):
|
class SmfUser(models.Model):
|
||||||
user = models.OneToOneField('auth.User',
|
user = models.OneToOneField("auth.User", primary_key=True, on_delete=models.CASCADE, related_name="smf")
|
||||||
primary_key=True,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='smf')
|
|
||||||
username = models.CharField(max_length=254)
|
username = models.CharField(max_length=254)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("access_smf", "Can access the SMF service"),)
|
||||||
("access_smf", "Can access the SMF service"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:52
|
||||||
|
|
||||||
|
import django.db.migrations.operations.special
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('teamspeak3', '0001_initial'), ('teamspeak3', '0002_auto_20161212_0133'), ('teamspeak3', '0003_teamspeak3user'), ('teamspeak3', '0004_service_permissions'), ('teamspeak3', '0005_stategroup')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('authentication', '0025_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='TSgroup',
|
||||||
|
fields=[
|
||||||
|
('ts_group_id', models.IntegerField(primary_key=True, serialize=False)),
|
||||||
|
('ts_group_name', models.CharField(max_length=30)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'TS Group',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserTSgroup',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('ts_group', models.ManyToManyField(to='teamspeak3.tsgroup')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'User TS Group',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AuthTS',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('auth_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.group')),
|
||||||
|
('ts_group', models.ManyToManyField(to='teamspeak3.tsgroup')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Auth / TS Group',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Teamspeak3User',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='teamspeak3', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('uid', models.CharField(max_length=254)),
|
||||||
|
('perm_key', models.CharField(max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_teamspeak3', 'Can access the Teamspeak3 service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='StateGroup',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('state', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='authentication.state')),
|
||||||
|
('ts_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='teamspeak3.tsgroup')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
@ -5,17 +5,12 @@ from allianceauth.authentication.models import State
|
|||||||
|
|
||||||
|
|
||||||
class Teamspeak3User(models.Model):
|
class Teamspeak3User(models.Model):
|
||||||
user = models.OneToOneField(User,
|
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE, related_name="teamspeak3")
|
||||||
primary_key=True,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='teamspeak3')
|
|
||||||
uid = models.CharField(max_length=254)
|
uid = models.CharField(max_length=254)
|
||||||
perm_key = models.CharField(max_length=254)
|
perm_key = models.CharField(max_length=254)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("access_teamspeak3", "Can access the Teamspeak3 service"),)
|
||||||
("access_teamspeak3", "Can access the Teamspeak3 service"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.uid
|
return self.uid
|
||||||
@ -26,7 +21,7 @@ class TSgroup(models.Model):
|
|||||||
ts_group_name = models.CharField(max_length=30)
|
ts_group_name = models.CharField(max_length=30)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'TS Group'
|
verbose_name = "TS Group"
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.ts_group_name
|
return self.ts_group_name
|
||||||
@ -37,7 +32,7 @@ class AuthTS(models.Model):
|
|||||||
ts_group = models.ManyToManyField(TSgroup)
|
ts_group = models.ManyToManyField(TSgroup)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'Auth / TS Group'
|
verbose_name = "Auth / TS Group"
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.auth_group.name
|
return self.auth_group.name
|
||||||
@ -48,7 +43,7 @@ class UserTSgroup(models.Model):
|
|||||||
ts_group = models.ManyToManyField(TSgroup)
|
ts_group = models.ManyToManyField(TSgroup)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'User TS Group'
|
verbose_name = "User TS Group"
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.user.name
|
return self.user.name
|
||||||
|
@ -8,7 +8,7 @@ class ConnectionError:
|
|||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.port = port
|
self.port = port
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f'Error connecting to host {self.ip} port {self.port}'
|
return f'Error connecting to host {self.ip} port {self.port}'
|
||||||
|
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ class TeamspeakError(Exception):
|
|||||||
msg = ts3_errors[self.code]
|
msg = ts3_errors[self.code]
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.code + ' ' + self.msg
|
return self.code + ' ' + self.msg
|
||||||
|
|
||||||
ts3_errors = {
|
ts3_errors = {
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:56
|
||||||
|
|
||||||
|
import django.db.migrations.operations.special
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
# Functions from the following migrations need manual copying.
|
||||||
|
# Move them and any dependencies into this file, then update the
|
||||||
|
# RunPython operations to refer to the local versions:
|
||||||
|
# allianceauth.services.modules.xenforo.migrations.0002_service_permissions
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('xenforo', '0001_initial'), ('xenforo', '0002_service_permissions')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='XenforoUser',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='xenforo', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('username', models.CharField(max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_xenforo', 'Can access the XenForo service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -2,17 +2,11 @@ from django.db import models
|
|||||||
|
|
||||||
|
|
||||||
class XenforoUser(models.Model):
|
class XenforoUser(models.Model):
|
||||||
user = models.OneToOneField('auth.User',
|
user = models.OneToOneField("auth.User", primary_key=True, on_delete=models.CASCADE, related_name="xenforo")
|
||||||
primary_key=True,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='xenforo')
|
|
||||||
username = models.CharField(max_length=254)
|
username = models.CharField(max_length=254)
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("access_xenforo", "Can access the XenForo service"),)
|
||||||
("access_xenforo", "Can access the XenForo service"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 00:59
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('srp', '0004_on_delete'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='srpfleetmain',
|
||||||
|
options={'default_permissions': (), 'permissions': (('access_srp', 'Can access SRP module'), ('add_srpfleetmain', 'Can access SRP module'))},
|
||||||
|
),
|
||||||
|
]
|
@ -1,31 +1,17 @@
|
|||||||
# Generated by Django 5.1.6 on 2025-03-04 01:26
|
# Generated by Django 5.1.6 on 2025-03-05 01:07
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
def create_permissions(apps, schema_editor):
|
|
||||||
User = apps.get_model('auth', 'User')
|
|
||||||
ContentType = apps.get_model('contenttypes', 'ContentType')
|
|
||||||
Permission = apps.get_model('auth', 'Permission')
|
|
||||||
ct = ContentType.objects.get_for_model(User)
|
|
||||||
Permission.objects.get_or_create(codename="srp_management", content_type=ct, name="srp_management")
|
|
||||||
|
|
||||||
|
|
||||||
def reverse(apps, schema_editor):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
replaces = [('srp', '0001_initial'), ('srp', '0002_srpuserrequest_srp_status_choices'), ('srp', '0003_make_strings_more_stringy'), ('srp', '0004_on_delete')]
|
replaces = [('srp', '0001_initial'), ('srp', '0002_srpuserrequest_srp_status_choices'), ('srp', '0003_make_strings_more_stringy'), ('srp', '0004_on_delete'), ('srp', '0005_alter_srpfleetmain_options')]
|
||||||
|
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
('eveonline', '0019_v5squash'),
|
('eveonline', '0019_v5squash'),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -43,7 +29,8 @@ class Migration(migrations.Migration):
|
|||||||
('fleet_commander', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.evecharacter')),
|
('fleet_commander', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.evecharacter')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'permissions': (('access_srp', 'Can access SRP module'),),
|
'permissions': (('access_srp', 'Can access SRP module'), ('add_srpfleetmain', 'Can access SRP module')),
|
||||||
|
'default_permissions': (),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
@ -62,6 +49,4 @@ class Migration(migrations.Migration):
|
|||||||
('srp_fleet_main', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='srp.srpfleetmain')),
|
('srp_fleet_main', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='srp.srpfleetmain')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.RunPython(create_permissions, reverse)
|
|
||||||
|
|
||||||
]
|
]
|
@ -15,31 +15,31 @@ class SrpFleetMain(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
('access_srp', 'Can access SRP module'),
|
("access_srp", "Can access SRP module"),
|
||||||
('add_srpfleetmain', 'Can access SRP module'),
|
("add_srpfleetmain", "Can access SRP module"),
|
||||||
# Intentionally Commented out
|
# Intentionally Commented out
|
||||||
# AAv0 has these in the Auth_ Content Type
|
# AAv0 has these in the Auth_ Content Type
|
||||||
# ('srp_management', 'Can Approve and Deny SRP requests, Can create an SRP Fleet'),
|
# ('srp_management', 'Can Approve and Deny SRP requests, Can create an SRP Fleet'),
|
||||||
)
|
)
|
||||||
default_permissions = ()
|
default_permissions = ()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.fleet_name
|
return self.fleet_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def total_cost(self):
|
def total_cost(self) -> int:
|
||||||
return sum(int(r.srp_total_amount) for r in self.srpuserrequest_set.all())
|
return sum(int(r.srp_total_amount) for r in self.srpuserrequest_set.all())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pending_requests(self):
|
def pending_requests(self):
|
||||||
return self.srpuserrequest_set.filter(srp_status='Pending').count()
|
return self.srpuserrequest_set.filter(srp_status="Pending").count()
|
||||||
|
|
||||||
|
|
||||||
class SrpUserRequest(models.Model):
|
class SrpUserRequest(models.Model):
|
||||||
SRP_STATUS_CHOICES = (
|
SRP_STATUS_CHOICES = (
|
||||||
('Pending', 'Pending'),
|
("Pending", "Pending"),
|
||||||
('Approved', 'Approved'),
|
("Approved", "Approved"),
|
||||||
('Rejected', 'Rejected'),
|
("Rejected", "Rejected"),
|
||||||
)
|
)
|
||||||
|
|
||||||
killboard_link = models.CharField(max_length=254, default="")
|
killboard_link = models.CharField(max_length=254, default="")
|
||||||
@ -53,5 +53,5 @@ class SrpUserRequest(models.Model):
|
|||||||
srp_ship_name = models.CharField(max_length=254, default="")
|
srp_ship_name = models.CharField(max_length=254, default="")
|
||||||
post_time = models.DateTimeField(default=timezone.now)
|
post_time = models.DateTimeField(default=timezone.now)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.character.character_name + ' SRP request for ' + self.srp_ship_name
|
return f"{self.character.character_name} SRP request for {self.srp_ship_name}"
|
||||||
|
@ -80,4 +80,4 @@ class Timer(models.Model):
|
|||||||
# default_permissions = ()
|
# default_permissions = ()
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return str(self.system) + ' ' + str(self.details)
|
return f"{self.system} {self.details}"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user