from django.contrib.auth.models import AbstractUser, Group from django.db import models from django.conf import settings from django.dispatch import receiver from rest_framework.authtoken.models import Token from django.db.models.signals import post_save from datetime import datetime class User(AbstractUser): TYPE_CHOICES = ( ('apiclient', 'API-Client'), ('oidcuser', 'OIDC User'), ('admin', 'Admin'), ) user_type = models.CharField( max_length=20, choices=TYPE_CHOICES, default='oidcuser', ) sub = models.CharField(max_length=150, blank=True, null=True) password = models.CharField(max_length=150, blank=True, null=True) @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_auth_token(sender, instance=None, created=False, **kwargs): if created: if instance.user_type == 'apiclient': Token.objects.create(user=instance) def construct_user(user_info): return User( sub=user_info['sub'], name=user_info['name'], first_name=user_info['given_name'], last_name=user_info['family_name'], email=user_info['email'], username=user_info['email'], ) class Site(models.Model): client = models.OneToOneField( User, related_name='site', blank=True, null=True) name = models.CharField(max_length=150, unique=True) description = models.TextField(max_length=300, blank=True) last_fetch = models.DateTimeField(default=datetime.utcfromtimestamp(0)) def __str__(self): return self.name def clientapi_get_deployments(self, all=False): services = {} for service in self.services.all(): ds = ( service.deployments .filter(user__user_type='oidcuser') .exclude(ssh_keys=None) ) if not all: ds = ds.filter(last_change__gt=self.last_fetch) # deployments with ssh keys services[service.name] = ds self.last_fetch = datetime.now() self.save() return services class Service(models.Model): name = models.CharField(max_length=150, unique=True) description = models.TextField(max_length=300, blank=True) site = models.ForeignKey( Site, related_name='services') groups = models.ManyToManyField( Group, related_name='services', blank=True) def __str__(self): return self.name + '@' + self.site.name class SSHPublicKey(models.Model): name = models.CharField(max_length=150, unique=True) key = models.TextField(max_length=1000) user = models.ForeignKey( User, related_name='ssh_keys') def __str__(self): return self.name class Deployment(models.Model): user = models.ForeignKey( User, related_name='deployments', on_delete=models.CASCADE, ) service = models.ForeignKey( Service, related_name='deployments', on_delete=models.CASCADE, ) # SET_NULL: we allow credentials to be deleted after deployment ssh_keys = models.ManyToManyField( SSHPublicKey, related_name='deployments', blank=True, ) last_change = models.DateTimeField( auto_now=True ) def __str__(self): return str(self.user) + '@' + str(self.service)