Source code for userextensions.models

"""

"""
import re
from django.conf import settings
from django.contrib.auth.models import User, Group
from django.db import models
from django.core.exceptions import ValidationError

from handyhelpers.managers import HandyHelperModelManager
from handyhelpers.models import HandyHelperBaseModel
from rest_framework.authtoken.models import Token


[docs]class Theme(HandyHelperBaseModel): """ This model tracks themes. It can be used to provide user preferred frontend styling options based on defined css files. """ name = models.CharField(max_length=32, unique=True, help_text='name of theme') css_file = models.CharField(max_length=255, unique=True, blank=True, null=True, help_text='path to css file for theme') def __str__(self): return self.name
[docs]class UserPreference(HandyHelperBaseModel): """ This table tracks user preferences. Fields include theme, recents_count, page_refresh_time, and start_page. """ user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='preference') theme = models.ForeignKey(Theme, blank=True, null=True, help_text='theme to use for web pages', on_delete=models.CASCADE) recents_count = models.IntegerField(default=25, blank=True, null=True, help_text='number of recents to keep a record of') page_refresh_time = models.IntegerField(default=5, blank=True, null=True, help_text='time, in minutes, to auto-refresh a page (where applicable') start_page = models.CharField(max_length=255, blank=True, null=True, help_text='url to redirect to after login') help_text_enable = models.BooleanField(default=True, help_text='enable help text and tooltips') timezone = models.CharField(max_length=32, blank=True, null=True, default='UTC', help_text='timezone to use when displaying time and datetime values') """https://stackoverflow.com/questions/48383549/how-to-show-local-time-in-template""" def __str__(self): return self.user.username
[docs]class UserRecent(HandyHelperBaseModel): """ This table stored recently visited urls. """ user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='recent') url = models.URLField(help_text='url endpoint') class Meta: unique_together = (('url', 'user'), ) def __str__(self): return self.url
[docs]class UserFavorite(HandyHelperBaseModel): """ This table stores user-defined favorites. """ user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='favorite') name = models.CharField(max_length=32, blank=True, null=True, help_text='name/label/reference for this favorite') url = models.URLField(help_text='url endpoint') class Meta: unique_together = (('url', 'user'), ) def __str__(self): return self.url
[docs]class ServiceAccount(HandyHelperBaseModel): """ This table stores service accounts and maps to a (service account) user and group """ user = models.OneToOneField(User, blank=True, null=True, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE) enabled = models.BooleanField(default=True, help_text='owner enable/disable state of service account') admin_enabled = models.BooleanField(default=True, help_text='admin enable/disable state of service account') description = models.CharField(max_length=254, blank=True, null=True, help_text='optional description') class Meta: unique_together = (('user', 'group'), ) def __str__(self): return self.user.username
[docs] def clean(self): """ clean/update/validate data before saving """ if not self.user: # If the SRV_ACCOUNT_GROUP_FILTER_LIST (list) settings variable is set, search for a matching regex in the # group name. Use the first match found. If no match is found or an exception is encountered, use the # group name as is. try: group_name = None for regex in getattr(settings, 'SRV_ACCOUNT_GROUP_FILTER_LIST', list()): match = re.match(regex, self.group.name) if match: group_name = match.group(1) break if not group_name: group_name = self.group.name except Exception as err: group_name = self.group.name # Create name based on prefix + group + suffix; prefix and/or suffix is required. The prefix & suffix values # are provided by django settings variables. If neither is set, a default suffix '_srv' will be used. prefix = getattr(settings, 'SRV_ACCOUNT_PREFIX', '') suffix = getattr(settings, 'SRV_ACCOUNT_SUFFIX', '') if not prefix and not suffix: suffix = '_srv' username = prefix + group_name + suffix else: username = self.user.username # before creating the service account, we need to get_or_create the user self.user = User.objects.get_or_create(username=username)[0] # add now add the new user to the matching group self.group.user_set.add(self.user) # check if multiple service accounts per group are allowed. This is set in the django settings file with # the ALLOW_MULTIPLE_SRV_ACCOUNTS variable. By default, multiple service accounts per group are allowed. To # limit service account creation to one per group, set ALLOW_MULTIPLE_SRV_ACCOUNTS=False if not self.pk: allow_multiple = getattr(settings, 'ALLOW_MULTIPLE_SRV_ACCOUNTS', True) existing = ServiceAccount.objects.filter(group=self.group) if existing and allow_multiple is False: raise ValidationError({'group': 'Multiple service accounts per group is currently not allowed. To ' 'enable multiple accounts per group, set ' 'ALLOW_MULTIPLE_SRV_ACCOUNTS=True in the django settings. '})
[docs] def save(self, *args, **kwargs): self.full_clean() super().save(*args, **kwargs)
[docs] def create_drf_token(self): """ create a drf token for this service account """ Token.objects.get_or_create(user=self.user)
class ServiceAccountTokenHistory(models.Model): """ This table track changes to a ServiceAccount API token refresh history """ objects = HandyHelperModelManager() actor = models.ForeignKey(User, null=True, on_delete=models.SET_NULL, help_text='user who refreshed token') srv_acct = models.ForeignKey(ServiceAccount, on_delete=models.CASCADE, help_text='') timestamp = models.DateTimeField(auto_now_add=True, help_text='date/time when this token refresh occurred') def __str__(self): return self.srv_acct.user.username