nomeelnoj
nomeelnoj

Reputation: 1

Automatically Update Django Profile when creating user

I am fairly new to Django and am hoping that this is as easy as I think it should be.

I have written a custom Django app that uses SaltStack as a back end for spinning up AWS instances. When an instance comes up, it adds the user who created it using their SSH key.

I need to give each user a UID and GID so we can create user accounts on linux hosts for them. Right now, this requires that an admin go in for each new user created and manually update these fields in the admin interface before a user can use the tool.

What I am hoping is that when a user is created, there is a way for Django to search through the profiles for the UID/GIDs that have already been used, increment by one, and assign it to the newly created user automatically.

Here is my Profile model:

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    linux_username = models.CharField(max_length=50, blank=True)
    linux_uid = models.CharField(max_length=10, blank=True)
    linux_gid = models.CharField(max_length=10, blank=True)
    linux_ssh_authkey = models.TextField(max_length=1000, blank=True)

@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.created(user=instance)
    instance.profile.save()

I hope this makes sense--when a user signs up, they choose a linux username and upload their SSH public key. But, we still have to go in as admins to populate the UID and GID fields. For example, I am 4001, if another user signed up, he would be 4002.

Is there a way to add a simple bit of code to the update_user_profile function that will auto-populate these fields?

I have tried messing around a little but cannot figure out how to poll the database for the next available UID/GID and set it for the new user.

Any help would be much appreciated!

Thanks!

Upvotes: 0

Views: 355

Answers (2)

nomeelnoj
nomeelnoj

Reputation: 1

I think I found the answer, though there may be a better way to do this. Thanks to Ajmal Noushad for pointing me in the right direction. Here is the final code that worked for me--if there is a better way to do this, please let me know.

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    linux_username = models.CharField(max_length=50, blank=True)
    linux_uid = models.CharField(max_length=10, blank=True)
    linux_gid = models.CharField(max_length=10, blank=True)
    linux_ssh_authkey = models.TextField(max_length=1000, blank=True)


@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

    try:
        last_user_joined = User.objects.all().order_by('date_joined').reverse()[1].profile
        instance.profile.linux_uid = str(int(last_user_joined.linux_uid)+1)
        instance.profile.linux_gid = str(int(last_user_joined.linux_gid)+1)
    except User.DoesNotExist:
        instance.profile.linux_uid = '0000'
        instance.profile.linux_gid = '0000'

    instance.profile.save()

This creates the profile for the user and automatically populates their UID with the next available UID in the list, but it is based on the user that is created last, not the highest UID. So if you create a user and manually set the UID to 4002, and another user already has 4003, the next user will automatically get 4003 as well. There is room for improvement, but I think this will work for now.

Thanks to all for your help!

Upvotes: 0

Ajmal Noushad
Ajmal Noushad

Reputation: 946

Yes, you can override the save() method of Profile for this.

class Profile(models.Model):
   user = models.OneToOneField(User, on_delete=models.CASCADE)
   linux_username = models.CharField(max_length=50, blank=True)
   linux_uid = models.CharField(max_length=10, blank=True)
   linux_gid = models.CharField(max_length=10, blank=True)
   linux_ssh_authkey = models.TextField(max_length=1000, blank=True)

   def save(self, force_insert=False, force_update=False, using=None,
         update_fields=None):  
       if not self.id:
         try:
            last_user_profile = User.objects.latest('date_joined').profile
            self.linux_uid = str(int(last_user_profile.linux_uid)+1)
            self.linux_gid = str(int(last_user_profile.linux_gid)+1)
         except User.DoesNotExist:
           self.linux_uid = '0000'
           self.linux_gid = '0000'
       return super(Profile, self).save()

The above code will get the profile of the latest user and add 1 to the UID and GID and store it. If there are no users already registered it will give default value of '0000' to both the UID and GIDs.

Upvotes: 1

Related Questions