From 9373589c52355f2d20f9b04013ce8e3a774af94b Mon Sep 17 00:00:00 2001 From: Nate Smith Date: Mon, 15 Jul 2019 20:38:11 -0500 Subject: [PATCH] code for adding a state field to users --- ttadmin/users/admin.py | 19 ++++++++++----- ttadmin/users/models.py | 51 ++++++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/ttadmin/users/admin.py b/ttadmin/users/admin.py index 5d2db04..73bad03 100644 --- a/ttadmin/users/admin.py +++ b/ttadmin/users/admin.py @@ -9,20 +9,27 @@ class PubkeyInline(admin.TabularInline): model = Pubkey extra = 1 -def bulk_review(madmin, req, qs): +def bulk_accept(madmin, req, qs): for townie in qs: - townie.reviewed = True + townie.state = 'accepted' townie.save() post_users_to_social(qs) -bulk_review.short_description = 'mark selected townies as reviewed' +bulk_accept.short_description = 'mark selected townies as accepted' + +def bulk_reject(madmin, req, qs): + for townie in qs: + townie.state = 'rejected' + townie.save() + +bulk_reject.short_description = 'mark selected townies as rejected' @admin.register(Townie) class TownieAdmin(admin.ModelAdmin): inlines = [PubkeyInline] - list_display = ('username', 'reviewed', 'email') - ordering = ('reviewed',) + list_display = ('username', 'state', 'email') readonly_fields = ('reasons', 'plans', 'socials') + ordering = ('state',) exclude = ('first_name', 'last_name', 'password', 'groups', 'user_permissions', 'last_login', 'is_staff', 'is_active', 'is_superuser') - actions = (bulk_review,) + actions = (bulk_accept, bulk_reject,) search_fields = ('username', 'email', 'displayname') diff --git a/ttadmin/users/models.py b/ttadmin/users/models.py index 0818b09..392e2d2 100644 --- a/ttadmin/users/models.py +++ b/ttadmin/users/models.py @@ -42,14 +42,37 @@ class Townie(User): class Meta: verbose_name = 'Townie' verbose_name_plural = 'Townies' + + # the actual values here have a leading int for sorting :( + UNREVIEWED = '0_unreviewed' + TEMPBAN = '1_tempban' + ACCEPTED = '2_accepted' + REJECTED = '3_rejected' + PERMABAN = '4_permaban' + STATE_CHOICES = ( + (REJECTED, 'Rejected'), + (ACCEPTED, 'Accepted'), + (UNREVIEWED, 'Unreviewed'), + (PERMABAN, 'Permanently Banned'), + (TEMPBAN, 'Temporarily Banned'), + ) shell = CharField(max_length=50, default="/bin/bash") - reviewed = BooleanField(default=False) + state = CharField(max_length=20, choices=STATE_CHOICES, default=UNREVIEWED) reasons = TextField(blank=True, null=False, default='') plans = TextField(blank=True, null=False, default='') socials = TextField(blank=True, null=False, default='') referral = CharField(max_length=100, null=True, blank=True) displayname = CharField(max_length=100, blank=False, null=False) - notes = TextField(blank=True, null=True) + notes = TextField(blank=True, null=True, + help_text='Use this field to share information about this user (reviewed or not) for other admins to see') + + @property + def accepted(self): + return self.ACCEPTED == self.state + + @property + def unreviewed(self): + return self.UNREVIEWED == self.state @property def home(self): @@ -86,7 +109,7 @@ class Townie(User): """A VERY NOT IDEMPOTENT create function. Originally, I had ambitions to have this be idempotent and able to incrementally update a user as needed, but decided that was overkill for now.""" - assert(self.reviewed) + assert(self.accepted) dot_ssh_path = '/home/{}/.ssh'.format(self.username) error = _guarded_run(['sudo', @@ -208,7 +231,7 @@ def on_pubkey_post_save(sender, instance, **kwargs): townie = townie[0] - if townie.reviewed: + if townie.accepted: townie.write_authorized_keys() @@ -220,13 +243,17 @@ def on_townie_pre_save(sender, instance, **kwargs): existing = Townie.objects.get(id=instance.id) - # See if we need to create this user on disk. - if not existing.reviewed and instance.reviewed is True: + # See if we need to create the user on disk. + if existing.unreviewed and instance.accepted: logger.info('Creating user {} on disk.'.format(instance.username)) instance.create_on_disk() instance.send_welcome_email() instance.write_authorized_keys() return + else: + # This user state transition is currently undefined. In the future, we can check for things + # like bans/unbans and then take the appropriate action. + return # See if this user needs a rename on disk logger.info('checking for rename {} vs {}'.format( @@ -252,15 +279,3 @@ def _guarded_run(cmd_args, **run_args): issue_text='error while running {}: {}'.format( cmd_args, e)) return e - - -# things to consider: -# * what happens when a user is marked as not reviewed? -# * does this signal user deletion? Or does literal Townie deletion signal -# "needs to be removed from disk"? I think it makes the most sense for the -# latter to imply full user deletion. -# * I honestly can't even think of a reason to revert a user to "not reviewed" -# and perhaps it's best to just not make that possible. for now, though, I -# think I can ignore it. -# * what happens when a user needs to be banned? -# * the Townie should be deleted via post_delete signal