mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-08 20:10:17 +02:00
Merge branch 'v5-squash' into 'v5.x'
V5 Squash See merge request allianceauth/allianceauth!1697
This commit is contained in:
commit
35551b611b
56
allianceauth/analytics/migrations/0011_v5squash.py
Normal file
56
allianceauth/analytics/migrations/0011_v5squash.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 01:03
|
||||||
|
|
||||||
|
# This was built by Deleting Every Migration, Creating one from scratch
|
||||||
|
# And porting in anything necessary
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def add_aa_team_token(apps, schema_editor):
|
||||||
|
Tokens = apps.get_model('analytics', 'AnalyticsTokens')
|
||||||
|
token = Tokens()
|
||||||
|
|
||||||
|
token.type = 'GA-V4'
|
||||||
|
token.token = 'G-6LYSMYK8DE'
|
||||||
|
token.secret = 'KLlpjLZ-SRGozS5f5wb_kw'
|
||||||
|
token.name = 'AA Team Public Google Analytics (V4)'
|
||||||
|
token.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('analytics', '0001_initial'), ('analytics', '0002_add_AA_Team_Token'), ('analytics', '0003_Generate_Identifier'), ('analytics', '0004_auto_20211015_0502'), ('analytics', '0005_alter_analyticspath_ignore_path'), ('analytics', '0006_more_ignore_paths'), ('analytics', '0007_analyticstokens_secret'), ('analytics', '0008_add_AA_GA-4_Team_Token '), ('analytics', '0009_remove_analyticstokens_ignore_paths_and_more'), ('analytics', '0010_alter_analyticsidentifier_options')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AnalyticsIdentifier',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('identifier', models.UUIDField(default=uuid.uuid4, editable=False)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Analytics Identifier',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AnalyticsTokens',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=254)),
|
||||||
|
('type', models.CharField(choices=[('GA-U', 'Google Analytics Universal'), ('GA-V4', 'Google Analytics V4')], max_length=254)),
|
||||||
|
('token', models.CharField(max_length=254)),
|
||||||
|
('secret', models.CharField(blank=True, max_length=254)),
|
||||||
|
('send_stats', models.BooleanField(default=False)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
add_aa_team_token
|
||||||
|
),
|
||||||
|
]
|
@ -17,6 +17,7 @@ class AnalyticsIdentifier(SingletonModel):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = "Analytics Identifier"
|
verbose_name = "Analytics Identifier"
|
||||||
|
|
||||||
|
|
||||||
class AnalyticsTokens(models.Model):
|
class AnalyticsTokens(models.Model):
|
||||||
|
|
||||||
class Analytics_Type(models.TextChoices):
|
class Analytics_Type(models.TextChoices):
|
||||||
|
124
allianceauth/authentication/migrations/0025_v5squash.py
Normal file
124
allianceauth/authentication/migrations/0025_v5squash.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 02:44
|
||||||
|
|
||||||
|
import django.contrib.auth.models
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import allianceauth.authentication.models
|
||||||
|
|
||||||
|
|
||||||
|
def create_states(apps, schema_editor) -> None:
|
||||||
|
State = apps.get_model('authentication', 'State')
|
||||||
|
|
||||||
|
State.objects.update_or_create(name="Guest", defaults={'priority': 0, 'public': True})[0]
|
||||||
|
State.objects.update_or_create(name="Blue", defaults={'priority': 50, 'public': False})[0]
|
||||||
|
State.objects.update_or_create(name="Member", defaults={'priority': 100, 'public': False})[0]
|
||||||
|
|
||||||
|
|
||||||
|
def create_states_reverse(apps, schema_editor) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('authentication', '0001_initial'), ('authentication', '0002_auto_20160907_1914'), ('authentication', '0003_authservicesinfo_state'), ('authentication', '0004_create_permissions'), ('authentication', '0005_delete_perms'), ('authentication', '0006_auto_20160910_0542'), ('authentication', '0007_remove_authservicesinfo_is_blue'), ('authentication', '0008_set_state'), ('authentication', '0009_auto_20161021_0228'), ('authentication', '0010_only_one_authservicesinfo'), ('authentication', '0011_authservicesinfo_user_onetoonefield'), ('authentication', '0012_remove_add_delete_authservicesinfo_permissions'), ('authentication', '0013_service_modules'), ('authentication', '0014_fleetup_permission'), ('authentication', '0015_user_profiles'), ('authentication', '0016_ownershiprecord'), ('authentication', '0017_remove_fleetup_permission'), ('authentication', '0018_state_member_factions'), ('authentication', '0018_alter_state_name_length'), ('authentication', '0019_merge_20211026_0919'), ('authentication', '0020_userprofile_language_userprofile_night_mode'), ('authentication', '0021_alter_userprofile_language'), ('authentication', '0022_userprofile_theme'), ('authentication', '0023_alter_userprofile_language'), ('authentication', '0024_alter_userprofile_language')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('esi', '0012_fix_token_type_choices'),
|
||||||
|
('eveonline', '0019_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CharacterOwnership',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('owner_hash', models.CharField(max_length=28, unique=True)),
|
||||||
|
('character', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='character_ownership', to='eveonline.evecharacter')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='character_ownerships', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'default_permissions': ('change', 'delete'),
|
||||||
|
'ordering': ['user', 'character__character_name'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='State',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=32, unique=True)),
|
||||||
|
('priority', models.IntegerField(help_text='Users get assigned the state with the highest priority available to them.', unique=True)),
|
||||||
|
('public', models.BooleanField(default=False, help_text='Make this state available to any character.')),
|
||||||
|
('member_alliances', models.ManyToManyField(blank=True, help_text='Alliances to whose members this state is available.', to='eveonline.eveallianceinfo')),
|
||||||
|
('member_characters', models.ManyToManyField(blank=True, help_text='Characters to which this state is available.', to='eveonline.evecharacter')),
|
||||||
|
('member_corporations', models.ManyToManyField(blank=True, help_text='Corporations to whose members this state is available.', to='eveonline.evecorporationinfo')),
|
||||||
|
('permissions', models.ManyToManyField(blank=True, to='auth.permission')),
|
||||||
|
('member_factions', models.ManyToManyField(blank=True, help_text='Factions to whose members this state is available.', to='eveonline.evefactioninfo')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['-priority'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserProfile',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('main_character', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.evecharacter')),
|
||||||
|
('state', models.ForeignKey(default=allianceauth.authentication.models.get_guest_state_pk, on_delete=django.db.models.deletion.SET_DEFAULT, to='authentication.state')),
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
|
||||||
|
('night_mode', models.BooleanField(blank=True, null=True, verbose_name='Night Mode')),
|
||||||
|
('theme', models.CharField(blank=True, help_text='Bootstrap 5 Themes from https://bootswatch.com/ or Community Apps', max_length=200, null=True, verbose_name='Theme')),
|
||||||
|
('language', models.CharField(blank=True, choices=[('en', 'English'), ('cs-cz', 'Czech'), ('de', 'German'), ('es', 'Spanish'), ('it-it', 'Italian'), ('ja', 'Japanese'), ('ko-kr', 'Korean'), ('fr-fr', 'French'), ('ru', 'Russian'), ('nl-nl', 'Dutch'), ('pl-pl', 'Polish'), ('uk', 'Ukrainian'), ('zh-hans', 'Simplified Chinese')], default='', max_length=10, verbose_name='Language')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'default_permissions': ('change',),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Permission',
|
||||||
|
fields=[
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'proxy': True,
|
||||||
|
'verbose_name': 'permission',
|
||||||
|
'verbose_name_plural': 'permissions',
|
||||||
|
},
|
||||||
|
bases=('auth.permission',),
|
||||||
|
managers=[
|
||||||
|
('objects', django.contrib.auth.models.PermissionManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='User',
|
||||||
|
fields=[
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'proxy': True,
|
||||||
|
'verbose_name': 'user',
|
||||||
|
'verbose_name_plural': 'users',
|
||||||
|
},
|
||||||
|
bases=('auth.user',),
|
||||||
|
managers=[
|
||||||
|
('objects', django.contrib.auth.models.UserManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OwnershipRecord',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('owner_hash', models.CharField(db_index=True, max_length=28)),
|
||||||
|
('created', models.DateTimeField(auto_now=True)),
|
||||||
|
('character', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ownership_records', to='eveonline.evecharacter')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ownership_records', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['-created'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_states, create_states_reverse),
|
||||||
|
|
||||||
|
]
|
@ -16,22 +16,28 @@ 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: ClassVar[StateManager] = StateManager()
|
objects: ClassVar[StateManager] = StateManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['-priority']
|
ordering = ["-priority"]
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
@ -49,11 +55,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():
|
||||||
@ -61,76 +67,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,
|
theme = models.CharField( # noqa:DJ001 Null has a specific meaning, never set by user
|
||||||
null=True)
|
|
||||||
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"
|
null=True,
|
||||||
|
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
|
||||||
|
|
||||||
@ -138,16 +126,14 @@ 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: ClassVar[CharacterOwnershipManager] = CharacterOwnershipManager()
|
objects: ClassVar[CharacterOwnershipManager] = CharacterOwnershipManager()
|
||||||
|
|
||||||
@ -160,13 +146,13 @@ class CharacterOwnership(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
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) -> str:
|
def __str__(self) -> str:
|
||||||
return f"{self.user}: {self.character} on {self.created}"
|
return f"{self.user}: {self.character} on {self.created}"
|
||||||
|
52
allianceauth/corputils/migrations/0006_v5squash.py
Normal file
52
allianceauth/corputils/migrations/0006_v5squash.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 01:29
|
||||||
|
|
||||||
|
# This was built by Deleting Every Migration, Creating one from scratch
|
||||||
|
# And porting in anything necessary
|
||||||
|
# Some functions were skipped as they only make sense _if you are migrating in place_
|
||||||
|
# i.e. permissions migration
|
||||||
|
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('corputils', '0001_initial'), ('corputils', '0002_migrate_permissions'), ('corputils', '0003_granular_permissions'), ('corputils', '0004_member_models'), ('corputils', '0005_cleanup_permissions')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('esi', '0012_fix_token_type_choices'),
|
||||||
|
('eveonline', '0019_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CorpStats',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('last_update', models.DateTimeField(auto_now=True)),
|
||||||
|
('corp', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='eveonline.evecorporationinfo')),
|
||||||
|
('token', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='esi.token')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'corp stats',
|
||||||
|
'verbose_name_plural': 'corp stats',
|
||||||
|
'permissions': (('view_corp_corpstats', 'Can view corp stats of their corporation.'), ('view_alliance_corpstats', 'Can view corp stats of members of their alliance.'), ('view_state_corpstats', 'Can view corp stats of members of their auth state.')),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CorpMember',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('character_id', models.PositiveIntegerField()),
|
||||||
|
('character_name', models.CharField(max_length=37)),
|
||||||
|
('corpstats', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='members', to='corputils.corpstats')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['character_name'],
|
||||||
|
'unique_together': {('corpstats', 'character_id')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -48,7 +48,7 @@ class CorpStats(models.Model):
|
|||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
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 +101,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 +121,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 +134,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:
|
||||||
@ -158,7 +158,7 @@ class CorpMember(models.Model):
|
|||||||
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 +179,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 02:08
|
||||||
|
|
||||||
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,27 +28,16 @@ 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)),
|
||||||
|
('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={
|
|
||||||
'abstract': False,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='ManagedCorpGroup',
|
|
||||||
fields=[
|
|
||||||
('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')),
|
|
||||||
('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')),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
@ -56,16 +46,23 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='autogroupsconfig',
|
model_name='autogroupsconfig',
|
||||||
name='alliance_managed_groups',
|
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'),
|
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.CreateModel(
|
||||||
|
name='ManagedCorpGroup',
|
||||||
|
fields=[
|
||||||
|
('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')),
|
||||||
|
('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')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='autogroupsconfig',
|
model_name='autogroupsconfig',
|
||||||
name='corp_managed_groups',
|
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'),
|
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'),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -85,20 +85,20 @@ class AutogroupsConfig(models.Model):
|
|||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return 'States: ' + (' '.join(list(self.states.all().values_list('name', flat=True))) if self.pk else str(None))
|
return 'States: ' + (' '.join(list(self.states.all().values_list('name', flat=True))) if self.pk else str(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)
|
||||||
|
|
||||||
@ -239,6 +239,7 @@ class ManagedGroup(models.Model):
|
|||||||
def __str__(self) -> str:
|
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)
|
||||||
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 01:29
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('eveonline', '0017_alliance_and_corp_names_are_not_unique'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='evecharacter',
|
||||||
|
name='alliance_name',
|
||||||
|
field=models.CharField(blank=True, default='', max_length=254, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='evecharacter',
|
||||||
|
name='alliance_ticker',
|
||||||
|
field=models.CharField(blank=True, default='', max_length=5, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='evecharacter',
|
||||||
|
name='faction_name',
|
||||||
|
field=models.CharField(blank=True, default='', max_length=254, null=True),
|
||||||
|
),
|
||||||
|
]
|
73
allianceauth/eveonline/migrations/0019_v5squash.py
Normal file
73
allianceauth/eveonline/migrations/0019_v5squash.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 02:19
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('eveonline', '0001_initial'), ('eveonline', '0002_remove_eveapikeypair_error_count'), ('eveonline', '0003_auto_20161026_0149'), ('eveonline', '0004_eveapikeypair_sso_verified'), ('eveonline', '0005_remove_eveallianceinfo_member_count'), ('eveonline', '0006_allow_null_evecharacter_alliance'), ('eveonline', '0007_unique_id_name'), ('eveonline', '0008_remove_apikeys'), ('eveonline', '0009_on_delete'), ('eveonline', '0010_alliance_ticker'), ('eveonline', '0011_ids_to_integers'), ('eveonline', '0012_index_additions'), ('eveonline', '0013_evecorporationinfo_ceo_id'), ('eveonline', '0014_auto_20210105_1413'), ('eveonline', '0015_factions'), ('eveonline', '0016_character_names_are_not_unique'), ('eveonline', '0017_alliance_and_corp_names_are_not_unique'), ('eveonline', '0018_alter_evecharacter_alliance_name_and_more')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '__first__'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EveAllianceInfo',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('alliance_id', models.PositiveIntegerField(unique=True)),
|
||||||
|
('alliance_name', models.CharField(db_index=True, max_length=254)),
|
||||||
|
('alliance_ticker', models.CharField(max_length=254)),
|
||||||
|
('executor_corp_id', models.PositiveIntegerField()),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'indexes': [models.Index(fields=['executor_corp_id'], name='eveonline_e_executo_7f3280_idx')],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EveFactionInfo',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('faction_id', models.PositiveIntegerField(db_index=True, unique=True)),
|
||||||
|
('faction_name', models.CharField(max_length=254, unique=True)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EveCorporationInfo',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('corporation_id', models.PositiveIntegerField(unique=True)),
|
||||||
|
('corporation_name', models.CharField(db_index=True, max_length=254)),
|
||||||
|
('corporation_ticker', models.CharField(max_length=254)),
|
||||||
|
('member_count', models.IntegerField()),
|
||||||
|
('alliance', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.eveallianceinfo')),
|
||||||
|
('ceo_id', models.PositiveIntegerField(blank=True, default=None, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'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, 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')],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -81,9 +81,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) -> str:
|
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():
|
||||||
@ -102,8 +104,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
|
||||||
@ -153,8 +153,10 @@ class EveCorporationInfo(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
indexes = [models.Index(fields=['ceo_id',]),]
|
indexes = [models.Index(fields=['ceo_id',]),]
|
||||||
|
|
||||||
def __str__(self) -> str:
|
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)
|
||||||
@ -167,8 +169,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
|
||||||
@ -210,10 +210,10 @@ class EveCharacter(models.Model):
|
|||||||
corporation_name = models.CharField(max_length=254)
|
corporation_name = models.CharField(max_length=254)
|
||||||
corporation_ticker = models.CharField(max_length=5)
|
corporation_ticker = models.CharField(max_length=5)
|
||||||
alliance_id = models.PositiveIntegerField(blank=True, null=True, default=None)
|
alliance_id = models.PositiveIntegerField(blank=True, null=True, default=None)
|
||||||
alliance_name = models.CharField(max_length=254, blank=True, default='')
|
alliance_name = models.CharField(max_length=254, blank=True, null=True, default='') # noqa: DJ001
|
||||||
alliance_ticker = models.CharField(max_length=5, blank=True, default='')
|
alliance_ticker = models.CharField(max_length=5, blank=True, null=True, default='') # noqa: DJ001
|
||||||
faction_id = models.PositiveIntegerField(blank=True, default=None)
|
faction_id = models.PositiveIntegerField(blank=True, null=True, default=None)
|
||||||
faction_name = models.CharField(max_length=254, blank=True, default='')
|
faction_name = models.CharField(max_length=254, blank=True, null=True, default='') # noqa: DJ001
|
||||||
|
|
||||||
objects: ClassVar[EveCharacterManager] = EveCharacterManager()
|
objects: ClassVar[EveCharacterManager] = EveCharacterManager()
|
||||||
provider = EveCharacterProviderManager()
|
provider = EveCharacterProviderManager()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
from bravado.client import SwaggerClient
|
from bravado.client import SwaggerClient
|
||||||
from bravado.exception import HTTPError, HTTPNotFound, HTTPUnprocessableEntity
|
from bravado.exception import HTTPError, HTTPNotFound, HTTPUnprocessableEntity
|
||||||
@ -50,10 +51,10 @@ class Entity:
|
|||||||
def __str__(self) -> str:
|
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):
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 01:20
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import allianceauth.framework.api.user
|
||||||
|
|
||||||
|
|
||||||
|
def create_permissions(apps, schema_editor) -> None:
|
||||||
|
# Remnant of AAv0
|
||||||
|
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="fleetactivitytracking", content_type=ct, name="fleetactivitytracking")
|
||||||
|
Permission.objects.get_or_create(codename="fleetactivitytracking_statistics", content_type=ct, name="fleetactivitytracking_statistics")
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('fleetactivitytracking', '0001_initial'), ('fleetactivitytracking', '0002_auto_20160905_2220'), ('fleetactivitytracking', '0003_auto_20160906_2354'), ('fleetactivitytracking', '0004_make_strings_more_stringy'), ('fleetactivitytracking', '0005_remove_fat_name'), ('fleetactivitytracking', '0006_auto_20180803_0430'), ('fleetactivitytracking', '0007_sentinel_user')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('eveonline', '0019_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Fatlink',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('fatdatetime', models.DateTimeField(default=django.utils.timezone.now)),
|
||||||
|
('duration', models.PositiveIntegerField()),
|
||||||
|
('fleet', models.CharField(max_length=254)),
|
||||||
|
('hash', models.CharField(max_length=254, unique=True)),
|
||||||
|
('creator', models.ForeignKey(on_delete=models.SET(allianceauth.framework.api.user.get_sentinel_user), to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': ()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Fat',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('system', models.CharField(max_length=30)),
|
||||||
|
('shiptype', models.CharField(max_length=100)),
|
||||||
|
('station', models.CharField(max_length=125)),
|
||||||
|
('character', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.evecharacter')),
|
||||||
|
('fatlink', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fleetactivitytracking.fatlink')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('character', 'fatlink')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_permissions, reverse)
|
||||||
|
]
|
@ -13,6 +13,14 @@ 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))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
permissions = (
|
||||||
|
# Intentionally Commented out
|
||||||
|
# AAv0 has these in the Auth_ Content Type
|
||||||
|
# ('fleetactivitytracking', 'fleetactivitytracking'),
|
||||||
|
# ('fleetactivitytracking_statistics', 'fleetactivitytracking_statistics'),
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.fleet
|
return self.fleet
|
||||||
|
|
||||||
@ -26,7 +34,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) -> str:
|
def __str__(self) -> str:
|
||||||
return f"Fat-link for {self.character.character_name}"
|
return f"Fat-link for {self.character.character_name}"
|
||||||
|
102
allianceauth/groupmanagement/migrations/0020_v5squash.py
Normal file
102
allianceauth/groupmanagement/migrations/0020_v5squash.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 02:50
|
||||||
|
|
||||||
|
import django.contrib.auth.models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def create_permissions(apps, schema_editor) -> None:
|
||||||
|
# Remnant of AAv0
|
||||||
|
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="group_management", content_type=ct, name="group_management")
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('groupmanagement', '0001_initial'), ('groupmanagement', '0002_auto_20160906_2354'), ('groupmanagement', '0003_default_groups'), ('groupmanagement', '0004_authgroup'), ('groupmanagement', '0005_authgroup_public'), ('groupmanagement', '0006_request_groups_perm'), ('groupmanagement', '0007_on_delete'), ('groupmanagement', '0008_remove_authgroup_permissions'), ('groupmanagement', '0009_requestlog'), ('groupmanagement', '0010_authgroup_states'), ('groupmanagement', '0011_requestlog_date'), ('groupmanagement', '0012_group_leads'), ('groupmanagement', '0013_fix_requestlog_date_field'), ('groupmanagement', '0014_auto_20200918_1412'), ('groupmanagement', '0015_make_descriptions_great_again'), ('groupmanagement', '0016_remove_grouprequest_status_field'), ('groupmanagement', '0017_improve_groups_documentation'), ('groupmanagement', '0018_reservedgroupname'), ('groupmanagement', '0019_adding_restricted_to_groups')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('authentication', '0025_v5squash'),
|
||||||
|
('eveonline', '0019_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='GroupRequest',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('leave_request', models.BooleanField(default=0)),
|
||||||
|
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.group')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AuthGroup',
|
||||||
|
fields=[
|
||||||
|
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='auth.group')),
|
||||||
|
('internal', models.BooleanField(default=True, help_text='Internal group, users cannot see, join or request to join this group.<br>Used for groups such as Members, Corp_*, Alliance_* etc.<br><b>Overrides Hidden and Open options when selected.</b>')),
|
||||||
|
('hidden', models.BooleanField(default=True, help_text='Group is hidden from users but can still join with the correct link.')),
|
||||||
|
('open', models.BooleanField(default=False, help_text='Group is open and users will be automatically added upon request.<br>If the group is not open users will need their request manually approved.')),
|
||||||
|
('description', models.TextField(blank=True, help_text='Short description <i>(max. 512 characters)</i> of the group shown to users.', max_length=512)),
|
||||||
|
('group_leaders', models.ManyToManyField(blank=True, help_text='Group leaders can process requests for this group. Use the <code>auth.group_management</code> permission to allow a user to manage all groups.<br>', related_name='leads_groups', to=settings.AUTH_USER_MODEL)),
|
||||||
|
('public', models.BooleanField(default=False, help_text='Group is public. Any registered user is able to join this group, with visibility based on the other options set for this group.<br>Auth will not remove users from this group automatically when they are no longer authenticated.')),
|
||||||
|
('group_leader_groups', models.ManyToManyField(blank=True, help_text='Members of leader groups can process requests for this group. Use the <code>auth.group_management</code> permission to allow a user to manage all groups.<br>', related_name='leads_group_groups', to='auth.group')),
|
||||||
|
('states', models.ManyToManyField(blank=True, help_text='States listed here will have the ability to join this group provided they have the proper permissions.<br>', related_name='valid_states', to='authentication.state')),
|
||||||
|
('restricted', models.BooleanField(default=False, help_text='Group is restricted. This means that adding or removing users for this group requires a superuser admin.')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'default_permissions': (),
|
||||||
|
'permissions': (('request_groups', 'Can request non-public groups'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Group',
|
||||||
|
fields=[
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'group',
|
||||||
|
'indexes': [],
|
||||||
|
'proxy': True,
|
||||||
|
'verbose_name_plural': 'groups',
|
||||||
|
},
|
||||||
|
bases=('auth.group',),
|
||||||
|
managers=[
|
||||||
|
('objects', django.contrib.auth.models.GroupManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='RequestLog',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('request_type', models.BooleanField(null=True)),
|
||||||
|
('request_info', models.CharField(max_length=254)),
|
||||||
|
('action', models.BooleanField(default=0)),
|
||||||
|
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.group')),
|
||||||
|
('request_actor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('date', models.DateTimeField(auto_now_add=True)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ReservedGroupName',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(help_text='Name that can not be used for groups.', max_length=150, unique=True, verbose_name='name')),
|
||||||
|
('reason', models.TextField(help_text='Reason why this name is reserved.', verbose_name='reason')),
|
||||||
|
('created_by', models.CharField(help_text='Name of the user who created this entry.', max_length=255, verbose_name='created by')),
|
||||||
|
('created_at', models.DateTimeField(default=django.utils.timezone.now, help_text='Date when this entry was created', verbose_name='created at')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_permissions, reverse)
|
||||||
|
]
|
@ -53,7 +53,7 @@ class RequestLog(models.Model):
|
|||||||
def __str__(self) -> str:
|
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):
|
||||||
@ -176,6 +176,9 @@ class AuthGroup(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("request_groups", _("Can request non-public groups")),
|
("request_groups", _("Can request non-public groups")),
|
||||||
|
# Intentionally Commented out
|
||||||
|
# AAv0 has these in the Auth_ Content Type
|
||||||
|
# ('group_management', 'group_management'))
|
||||||
)
|
)
|
||||||
default_permissions = ()
|
default_permissions = ()
|
||||||
|
|
||||||
|
100
allianceauth/hrapplications/migrations/0008_v5squash.py
Normal file
100
allianceauth/hrapplications/migrations/0008_v5squash.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 04:31
|
||||||
|
|
||||||
|
import sortedm2m.fields
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def create_permissions(apps, schema_editor) -> None:
|
||||||
|
# Remnant of AAv0
|
||||||
|
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="human_resources", content_type=ct, name="human_resources")
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('hrapplications', '0001_initial'), ('hrapplications', '0002_choices_for_questions'), ('hrapplications', '0003_applicationquestion_multi_select'), ('hrapplications', '0004_make_strings_more_stringy'), ('hrapplications', '0005_sorted_questions'), ('hrapplications', '0006_remove_legacy_models'), ('hrapplications', '0007_auto_20200918_1412')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('eveonline', '0019_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ApplicationQuestion',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('title', models.CharField(max_length=254, verbose_name='Question')),
|
||||||
|
('help_text', models.CharField(blank=True, max_length=254, null=True)),
|
||||||
|
('multi_select', models.BooleanField(default=False)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ApplicationForm',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('corp', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='eveonline.evecorporationinfo')),
|
||||||
|
('questions', sortedm2m.fields.SortedManyToManyField(help_text=None, to='hrapplications.applicationquestion')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ApplicationChoice',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('choice_text', models.CharField(max_length=200, verbose_name='Choice')),
|
||||||
|
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='hrapplications.applicationquestion')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Application',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('approved', models.BooleanField(blank=True, default=None, null=True)),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('form', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='applications', to='hrapplications.applicationform')),
|
||||||
|
('reviewer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('reviewer_character', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.evecharacter')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='applications', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('approve_application', 'Can approve applications'), ('reject_application', 'Can reject applications'), ('view_apis', 'Can view applicant APIs')),
|
||||||
|
'unique_together': {('form', 'user')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ApplicationComment',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('text', models.TextField()),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='hrapplications.application')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ApplicationResponse',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('answer', models.TextField()),
|
||||||
|
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='responses', to='hrapplications.application')),
|
||||||
|
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='hrapplications.applicationquestion')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('question', 'application')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_permissions, reverse)
|
||||||
|
|
||||||
|
]
|
@ -30,6 +30,13 @@ 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)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
permissions = (
|
||||||
|
# Intentionally Commented out
|
||||||
|
# AAv0 has these in the Auth_ Content Type
|
||||||
|
# ('human_resources', 'human_resources'))
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return str(self.corp)
|
return str(self.corp)
|
||||||
|
|
||||||
@ -44,11 +51,11 @@ class Application(models.Model):
|
|||||||
|
|
||||||
objects: ClassVar[ApplicationManager] = ApplicationManager()
|
objects: ClassVar[ApplicationManager] = ApplicationManager()
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
('approve_application', 'Can approve applications'), ('reject_application', 'Can reject applications'),
|
('approve_application', 'Can approve applications'),
|
||||||
('view_apis', 'Can view applicant APIs'),)
|
('reject_application', 'Can reject applications'),
|
||||||
|
)
|
||||||
unique_together = ('form', 'user')
|
unique_together = ('form', 'user')
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
@ -76,14 +83,14 @@ 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) -> str:
|
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)
|
||||||
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
@ -41,10 +41,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
|
||||||
@ -54,7 +51,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
|
||||||
@ -63,10 +60,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="",
|
||||||
@ -79,7 +73,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)
|
||||||
@ -125,14 +119,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
|
||||||
|
46
allianceauth/notifications/migrations/0006_v5squash.py
Normal file
46
allianceauth/notifications/migrations/0006_v5squash.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 01:24
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def create_permissions(apps, schema_editor) -> None:
|
||||||
|
# Remnant of AAv0
|
||||||
|
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="logging_notifications", content_type=ct, name="logging_notifications")
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('notifications', '0001_initial'), ('notifications', '0002_auto_20160910_1649'), ('notifications', '0003_make_strings_more_stringy'), ('notifications', '0004_performance_tuning'), ('notifications', '0005_fix_level_choices')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Notification',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('level', models.CharField(choices=[('danger', 'danger'), ('warning', 'warning'), ('info', 'info'), ('success', 'success')], default='info', max_length=10)),
|
||||||
|
('title', models.CharField(max_length=254)),
|
||||||
|
('message', models.TextField()),
|
||||||
|
('timestamp', models.DateTimeField(auto_now_add=True, db_index=True)),
|
||||||
|
('viewed', models.BooleanField(db_index=True, default=False)),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={'permissions': ()},
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_permissions, reverse)
|
||||||
|
]
|
@ -59,15 +59,22 @@ class Notification(models.Model):
|
|||||||
|
|
||||||
objects: ClassVar[NotificationManager] = NotificationManager()
|
objects: ClassVar[NotificationManager] = NotificationManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
permissions = (
|
||||||
|
# Intentionally Commented out
|
||||||
|
# AAv0 has these in the Auth_ Content Type
|
||||||
|
# ('logging_notifications', 'logging_notifications')
|
||||||
|
)
|
||||||
|
|
||||||
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)
|
||||||
|
67
allianceauth/optimer/migrations/0005_v5squash.py
Normal file
67
allianceauth/optimer/migrations/0005_v5squash.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 01:26
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def create_permissions(apps, schema_editor) -> None:
|
||||||
|
# Remnant of AAv0
|
||||||
|
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="optimer_management", content_type=ct, name="optimer_management")
|
||||||
|
Permission.objects.get_or_create(codename="optimer_view", content_type=ct, name="optimer_view")
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('optimer', '0001_initial'), ('optimer', '0002_auto_20170413_0442'), ('optimer', '0003_make_strings_more_stringy'), ('optimer', '0004_on_delete'), ('optimer', '0005_add_type_and_description')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('eveonline', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OpTimerType',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('type', models.CharField(default='', max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['type'],
|
||||||
|
'default_permissions': (),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='optimer',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('doctrine', models.CharField(default='', max_length=254)),
|
||||||
|
('system', models.CharField(default='', max_length=254)),
|
||||||
|
('start', models.DateTimeField(default=datetime.datetime.now)),
|
||||||
|
('duration', models.CharField(default='', max_length=25)),
|
||||||
|
('operation_name', models.CharField(default='', max_length=254)),
|
||||||
|
('fc', models.CharField(default='', max_length=254)),
|
||||||
|
('post_time', models.DateTimeField(default=django.utils.timezone.now)),
|
||||||
|
('eve_character', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.evecharacter')),
|
||||||
|
('description', models.TextField(blank=True, default='')),
|
||||||
|
('type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='optimer.optimertype')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['start'],
|
||||||
|
'default_permissions': (),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_permissions, reverse)
|
||||||
|
]
|
@ -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) -> str:
|
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,19 @@ 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 = ()
|
||||||
|
# Intentionally Commented out
|
||||||
|
# AAv0 has these in the Auth_ Content Type
|
||||||
|
# permissions = (
|
||||||
|
# ('optimer_view', 'optimer_view'),
|
||||||
|
# ('optimer_management', 'optimer_management'),
|
||||||
|
# )
|
||||||
|
|
||||||
def __str__(self) -> str:
|
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}"
|
||||||
|
@ -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')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,33 @@
|
|||||||
|
# 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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'permissions': (('access_discord', 'Can access the Discord service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -26,45 +26,29 @@ 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: ClassVar[DiscordUserManager] = DiscordUserManager()
|
objects: ClassVar[DiscordUserManager] = DiscordUserManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
default_permissions = ()
|
||||||
("access_discord", "Can access the Discord service"),
|
permissions = (("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
|
||||||
@ -81,15 +65,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:
|
||||||
@ -105,27 +85,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:
|
||||||
@ -136,23 +111,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
|
||||||
|
|
||||||
@ -169,37 +139,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,31 @@
|
|||||||
|
# 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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'permissions': (('access_discourse', 'Can access the Discourse service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -3,18 +3,12 @@ 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 = (
|
default_permissions = ()
|
||||||
("access_discourse", "Can access the Discourse service"),
|
permissions = (("access_discourse", "Can access the Discourse service"),)
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
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,32 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'permissions': (('access_ips4', 'Can access the IPS4 service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -3,18 +3,13 @@ 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 = (
|
default_permissions = ()
|
||||||
("access_ips4", "Can access the IPS4 service"),
|
permissions = (("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,41 @@
|
|||||||
|
# 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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'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: ClassVar[MumbleManager] = MumbleManager()
|
objects: ClassVar[MumbleManager] = 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,18 +128,18 @@ 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):
|
||||||
if groups is None:
|
if groups is None:
|
||||||
groups = self.user.groups.all()
|
groups = self.user.groups.all()
|
||||||
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()
|
||||||
@ -155,6 +152,7 @@ class MumbleUser(AbstractServiceModel):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
default_permissions = ()
|
||||||
permissions = (
|
permissions = (
|
||||||
("access_mumble", "Can access the Mumble service"),
|
("access_mumble", "Can access the Mumble service"),
|
||||||
("view_connection_history", "Can access the connection history of the Mumble service"),
|
("view_connection_history", "Can access the connection history of the Mumble service"),
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
def create_permissions(apps, schema_editor) -> None:
|
||||||
|
# Remnant of AAv0
|
||||||
|
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="jabber_broadcast", content_type=ct, name="jabber_broadcast")
|
||||||
|
Permission.objects.get_or_create(codename="jabber_broadcast_all", content_type=ct, name="jabber_broadcast_all")
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'permissions': (('access_openfire', 'Can access the Openfire service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_permissions, reverse)
|
||||||
|
]
|
@ -2,17 +2,18 @@ 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:
|
||||||
|
default_permissions = ()
|
||||||
permissions = (
|
permissions = (
|
||||||
("access_openfire", "Can access the Openfire service"),
|
("access_openfire", "Can access the Openfire service"),
|
||||||
|
# Intentionally Commented out
|
||||||
|
# AAv0 has these in the Auth_ Content Type
|
||||||
|
# ('jabber_broadcast', 'jabber_broadcast'),
|
||||||
|
# ('jabber_broadcast_all', 'jabber_broadcast_all'),
|
||||||
)
|
)
|
||||||
def __str__(self):
|
|
||||||
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'permissions': (('access_phpbb3', 'Can access the phpBB3 service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -2,16 +2,12 @@ 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 = (
|
default_permissions = ()
|
||||||
("access_phpbb3", "Can access the phpBB3 service"),
|
permissions = (("access_phpbb3", "Can access the phpBB3 service"),)
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'permissions': (('access_smf', 'Can access the SMF service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -2,16 +2,12 @@ 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 = (
|
default_permissions = ()
|
||||||
("access_smf", "Can access the SMF service"),
|
permissions = (("access_smf", "Can access the SMF service"),)
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
# 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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'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,13 @@ 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 = (
|
default_permissions = ()
|
||||||
("access_teamspeak3", "Can access the Teamspeak3 service"),
|
permissions = (("access_teamspeak3", "Can access the Teamspeak3 service"),)
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.uid
|
return self.uid
|
||||||
@ -26,7 +22,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 +33,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 +44,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,31 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
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={
|
||||||
|
'default_permissions': (),
|
||||||
|
'permissions': (('access_xenforo', 'Can access the XenForo service'),),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -2,17 +2,12 @@ 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 = (
|
default_permissions = ()
|
||||||
("access_xenforo", "Can access the XenForo service"),
|
permissions = (("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'))},
|
||||||
|
),
|
||||||
|
]
|
66
allianceauth/srp/migrations/0006_v5squash.py
Normal file
66
allianceauth/srp/migrations/0006_v5squash.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-05 01:07
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def create_permissions(apps, schema_editor) -> None:
|
||||||
|
# Remnant of AAv0
|
||||||
|
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) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('eveonline', '0019_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SrpFleetMain',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('fleet_name', models.CharField(default='', max_length=254)),
|
||||||
|
('fleet_doctrine', models.CharField(default='', max_length=254)),
|
||||||
|
('fleet_time', models.DateTimeField()),
|
||||||
|
('fleet_srp_code', models.CharField(default='', max_length=254)),
|
||||||
|
('fleet_srp_status', models.CharField(default='', max_length=254)),
|
||||||
|
('fleet_srp_aar_link', models.CharField(default='', max_length=254)),
|
||||||
|
('fleet_commander', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.evecharacter')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('access_srp', 'Can access SRP module'), ('add_srpfleetmain', 'Can access SRP module')),
|
||||||
|
'default_permissions': (),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SrpUserRequest',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('killboard_link', models.CharField(default='', max_length=254)),
|
||||||
|
('after_action_report_link', models.CharField(default='', max_length=254)),
|
||||||
|
('additional_info', models.CharField(default='', max_length=254)),
|
||||||
|
('srp_status', models.CharField(choices=[('Pending', 'Pending'), ('Approved', 'Approved'), ('Rejected', 'Rejected')], default='Pending', max_length=8)),
|
||||||
|
('srp_total_amount', models.BigIntegerField(default=0)),
|
||||||
|
('kb_total_loss', models.BigIntegerField(default=0)),
|
||||||
|
('srp_ship_name', models.CharField(default='', max_length=254)),
|
||||||
|
('post_time', models.DateTimeField(default=django.utils.timezone.now)),
|
||||||
|
('character', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.evecharacter')),
|
||||||
|
('srp_fleet_main', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='srp.srpfleetmain')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_permissions, reverse)
|
||||||
|
]
|
@ -13,26 +13,33 @@ class SrpFleetMain(models.Model):
|
|||||||
fleet_commander = models.ForeignKey(EveCharacter, null=True, on_delete=models.SET_NULL)
|
fleet_commander = models.ForeignKey(EveCharacter, null=True, on_delete=models.SET_NULL)
|
||||||
fleet_srp_aar_link = models.CharField(max_length=254, default="")
|
fleet_srp_aar_link = models.CharField(max_length=254, default="")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (('access_srp', 'Can access SRP module'),)
|
permissions = (
|
||||||
|
("access_srp", "Can access SRP module"),
|
||||||
|
("add_srpfleetmain", "Can access SRP module"),
|
||||||
|
# Intentionally Commented out
|
||||||
|
# AAv0 has these in the Auth_ Content Type
|
||||||
|
# ('srp_management', 'Can Approve and Deny SRP requests, Can create an SRP Fleet'),
|
||||||
|
)
|
||||||
|
default_permissions = ()
|
||||||
|
|
||||||
def __str__(self) -> str:
|
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="")
|
||||||
@ -47,4 +54,4 @@ class SrpUserRequest(models.Model):
|
|||||||
post_time = models.DateTimeField(default=timezone.now)
|
post_time = models.DateTimeField(default=timezone.now)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
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}"
|
||||||
|
55
allianceauth/timerboard/migrations/0008_v5squash.py
Normal file
55
allianceauth/timerboard/migrations/0008_v5squash.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-04 01:27
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def create_permissions(apps, schema_editor) -> None:
|
||||||
|
# Remnant of AAv0
|
||||||
|
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="timer_management", content_type=ct, name="timer_management")
|
||||||
|
Permission.objects.get_or_create(codename="timer_view", content_type=ct, name="timer_view")
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('timerboard', '0001_initial'), ('timerboard', '0002_make_strings_more_stringy'), ('timerboard', '0003_on_delete'), ('timerboard', '0004_timer_type'), ('timerboard', '0005_alter_timer_planet_moon'), ('timerboard', '0006_alter_timer_objective_alter_timer_structure_and_more'), ('timerboard', '0007_alter_timer_structure')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('eveonline', '0019_v5squash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Timer',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('details', models.CharField(default='', max_length=254)),
|
||||||
|
('system', models.CharField(default='', max_length=254)),
|
||||||
|
('planet_moon', models.CharField(blank=True, default='', max_length=254)),
|
||||||
|
('structure', models.CharField(choices=[('POCO', 'POCO'), ('Orbital Skyhook', 'Orbital Skyhook'), ('I-HUB', 'Sovereignty Hub'), ('TCU', 'TCU'), ('POS[S]', 'POS [S]'), ('POS[M]', 'POS [M]'), ('POS[L]', 'POS [L]'), ('Astrahus', 'Astrahus'), ('Fortizar', 'Fortizar'), ('Keepstar', 'Keepstar'), ('Raitaru', 'Raitaru'), ('Azbel', 'Azbel'), ('Sotiyo', 'Sotiyo'), ('Athanor', 'Athanor'), ('Tatara', 'Tatara'), ('Pharolux Cyno Beacon', 'Cyno Beacon'), ('Tenebrex Cyno Jammer', 'Cyno Jammer'), ('Ansiblex Jump Gate', 'Ansiblex Jump Gate'), ('Mercenary Den', 'Mercenary Den'), ('Moon Mining Cycle', 'Moon Mining Cycle'), ('Metenox Moon Drill', 'Metenox Moon Drill'), ('Other', 'Other')], default='Other', max_length=254)),
|
||||||
|
('objective', models.CharField(choices=[('Friendly', 'Friendly'), ('Hostile', 'Hostile'), ('Neutral', 'Neutral')], default='Neutral', max_length=254)),
|
||||||
|
('eve_time', models.DateTimeField()),
|
||||||
|
('important', models.BooleanField(default=False)),
|
||||||
|
('corp_timer', models.BooleanField(default=False)),
|
||||||
|
('eve_character', models.ForeignKey(null=True, on_delete=models.deletion.SET_NULL, to='eveonline.evecharacter')),
|
||||||
|
('eve_corp', models.ForeignKey(on_delete=models.deletion.CASCADE, to='eveonline.evecorporationinfo')),
|
||||||
|
('user', models.ForeignKey(null=True, on_delete=models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('timer_type', models.CharField(choices=[('UNSPECIFIED', 'Not Specified'), ('SHIELD', 'Shield'), ('ARMOR', 'Armor'), ('HULL', 'Hull'), ('FINAL', 'Final'), ('ANCHORING', 'Anchoring'), ('UNANCHORING', 'Unanchoring'), ('ABANDONED', 'Abandoned')], default='UNSPECIFIED', max_length=254)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['eve_time'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.RunPython(create_permissions, reverse)
|
||||||
|
]
|
@ -73,6 +73,12 @@ class Timer(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['eve_time']
|
ordering = ['eve_time']
|
||||||
|
# Intentionally Commented out
|
||||||
|
# AAv0 has these in the Auth_ Content Type
|
||||||
|
# permissions = (
|
||||||
|
# ('timer_view', 'Can view Timerboard Timers'),
|
||||||
|
# ('timer_management', 'Can Manage Timerboard timers'))
|
||||||
|
# default_permissions = ()
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return str(self.system) + ' ' + str(self.details)
|
return f"{self.system} {self.details}"
|
||||||
|
@ -40,10 +40,10 @@ To use and administer this feature, users will require some of the following.
|
|||||||
+----------------------+------------------+------------------------------------------------------------+
|
+----------------------+------------------+------------------------------------------------------------+
|
||||||
| Permission | Admin Site | Auth Site |
|
| Permission | Admin Site | Auth Site |
|
||||||
+======================+==================+============================================================+
|
+======================+==================+============================================================+
|
||||||
| auth.access_srp | None | Can create an SRP request from a fleet |
|
| srp.access_srp | None | Can create an SRP request from a fleet |
|
||||||
+----------------------+------------------+------------------------------------------------------------+
|
+----------------------+------------------+------------------------------------------------------------+
|
||||||
| auth.srp_management | None | Can Approve and Deny SRP requests, Can create an SRP Fleet |
|
| auth.srp_management | None | Can Approve and Deny SRP requests, Can create an SRP Fleet |
|
||||||
+----------------------+------------------+------------------------------------------------------------+
|
+----------------------+------------------+------------------------------------------------------------+
|
||||||
| srp.add_srpfleetmain | Can Add Model | Can Create an SRP Fleet |
|
| srp.add_srpfleetmain | None | Can Create an SRP Fleet |
|
||||||
+----------------------+------------------+------------------------------------------------------------+
|
+----------------------+------------------+------------------------------------------------------------+
|
||||||
```
|
```
|
||||||
|
Loading…
x
Reference in New Issue
Block a user