# SPDX-FileCopyrightText: 2024 Thomas Breitner <t.breitner@csl.mpg.de>
#
# SPDX-License-Identifier: EUPL-1.2
from django.db import models
from django.forms.models import model_to_dict
from django.contrib.auth.models import AbstractUser
from .profile_management import user_tasks
[docs]
class CustomUser(AbstractUser):
"""
CustomUser model for eucrim users with additional attributes.
See also: http://docs.wagtail.io/en/v2.0.1/advanced_topics/customisation/custom_user_models.html
"""
EDITOR_IN_CHIEF = "10_EIC"
MANAGING_DIRECTOR = "20_MDR"
EDITOR = "30_EDT"
EDITORIAL_BOARD = "40_EDB"
LANGUAGE_CONSULTANT = "50_LCN"
TYPESET = "60_TYS"
WEB = "70_WEB"
STUDENT_ASSISTANT = "80_SAS"
EDITORIAL_ASSISTENT = "90_EAS"
NOROLE = "99_NRL"
# the last role is the default "no-role" and should not be printed out
# in the templates
TEAM_ROLE_CHOICES = (
(EDITOR_IN_CHIEF, "Editor in Chief"),
(MANAGING_DIRECTOR, "Managing Editor"),
(EDITOR, "Editor"),
(EDITORIAL_BOARD, "Editorial Board"),
(LANGUAGE_CONSULTANT, "Language Consultant"),
(TYPESET, "Typeset"),
(WEB, "Developer"),
(STUDENT_ASSISTANT, "Student Assistent"),
(EDITORIAL_ASSISTENT, "Editorial Assistent"),
(NOROLE, "no role"),
)
is_association_manager = models.BooleanField(
default=False,
help_text="If set, this user is designated to edit association data. "
"No profile page is created. The user is informed about his "
"new possibilities via email.",
)
is_author = models.BooleanField(
default=True,
help_text="If set, an Author page will be created for this user.",
)
is_team = models.BooleanField(
default=False,
help_text="If set, only a small subset of the AuthorPage fields "
"will be used. Team members are found in the printed issue "
"in the imprint.",
)
team_role = models.CharField(
max_length=6,
choices=TEAM_ROLE_CHOICES,
default=NOROLE,
help_text="Role in eucrim team, like stated in the imprint of the "
'printed issue; e.g. "Managing Editor", defaults to a quasi '
'non-role "Member"',
)
@property
def get_profilepage(self):
from eucrim.profile.models import ProfilePage
try:
profile_page = ProfilePage.objects.get(user=self)
except ProfilePage.DoesNotExist:
profile_page = None
return profile_page
[docs]
@classmethod
def from_db(cls, db, field_names, values):
"""
Get old values from db.
see: https://docs.djangoproject.com/el/2.1/ref/models/instances/#customizing-model-loading
"""
instance = super().from_db(db, field_names, values)
instance._loaded_values = dict(zip(field_names, values))
return instance
[docs]
def save(self, *args, **kwargs):
"""
Custom model save method to trigger some tasks. We need to know if this
instance is a new or modified one, we need to know if certain fields
have changed (e.g. if user had not is_author flag but does has now,
we need to create a ProfilePage for him). So we are interessted in the
fields that have changed and their new value.
"""
FIELDS_TO_MONITOR = {
"is_team",
"is_author",
"is_association_manager",
}
if self._state.adding:
user_state_action = "created"
else:
user_state_action = "modified"
if self._state.adding:
fields_changed = dict()
else:
# only check for changed fields when not adding a completly new
# user instance
fields_loaded = {
_key: self._loaded_values[_key] for _key in FIELDS_TO_MONITOR
}
fields_new = model_to_dict(self, fields=FIELDS_TO_MONITOR)
# comparing two sets, using difference(), here with the "-" notation
fields_changed = set(fields_new.items()) - set(fields_loaded.items())
fields_changed = dict(fields_changed)
# Calling save in order to get the pk:
super().save(*args, **kwargs)
# Custom logic for creating and updateing corresponding ProfilePage
# instances:
# TODO: refactor
user_tasks(self, user_state_action, fields_changed)