diff --git a/README.md b/README.md index 0eafc90..c2e7bdc 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ _Being an adminstrative tool written in Django for _. * Python 3.5+ * PostgreSQL 9+ + * Ubuntu or Debian ## Installation / setup diff --git a/scripts/create_keyfile.py b/scripts/create_keyfile.py old mode 100644 new mode 100755 diff --git a/scripts/rename_user.py b/scripts/rename_user.py new file mode 100755 index 0000000..9e657e7 --- /dev/null +++ b/scripts/rename_user.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""This script wraps the usermod command to allow user account renames via +sudoers.""" +import os +import sys +import subprocess + + +def rename_user(old_username, new_username): + """Given an old and a new username, renames user on disk with usermod. + Raises if the usermod call fails.""" + args = [ + 'usermod', + '-l', + new_username, + '-m', + '-d', + os.path.join('/home', new_username), + old_username + ] + subprocess.run(args, check=True) + + +def main(argv): + if len(argv) < 3: + print('[rename_user] Too few arguments passed.', file=sys.stderr) + return 1 + + try: + rename_user(argv[1], argv[2]) + except subprocess.CalledProcessError as e: + print('[rename_user] {}'.format(e), file=sys.stderr) + return 2 + + return 0 + + +if __name__ == '__main__': + exit(main(sys.argv)) diff --git a/serversetup.md b/serversetup.md index 8a87e58..6ed4a5f 100644 --- a/serversetup.md +++ b/serversetup.md @@ -14,11 +14,14 @@ * create ttadmin user * ttadmin db user (or just rely on ident..?) / database created -* copy `create_keyfile.py` from `scripts/` and put it in `/opt/bin/`. -* `chmod o+x /opt/bin/create_keyfile.py`` +* copy `create_keyfile.py` from `scripts/` and put it in `/opt/bin/`. +* copy `rename_user.py` from `scripts/` and put it in `/tilde/bin/`. +* `chmod u+x /opt/bin/create_keyfile.py`` * add to sudoers: - ttadmin ALL=(ALL)NOPASSWD:/usr/sbin/adduser,/bin/mkdir,/opt/bin/create_keyfile.py + ``` + ttadmin ALL=(ALL)NOPASSWD:/usr/sbin/adduser,/bin/mkdir,/opt/bin/create_keyfile.py,/tilde/bin/rename_user.py + ``` * have virtualenv with python 3.5+ ready, install tildetown-admin package into it * run django app as wsgi container through gunicorn as the ttadmin user with venv active diff --git a/ttadmin/users/forms.py b/ttadmin/users/forms.py index 0dcd555..9b29d3e 100644 --- a/ttadmin/users/forms.py +++ b/ttadmin/users/forms.py @@ -34,6 +34,7 @@ def validate_displayname(display_name): if not DISPLAY_NAME_RE.match(display_name): raise ValidationError("Valid characters: a-z, A-Z, 0-9, -, _, and '.") + def validate_pubkey(pubkey): # TODO see if I can get the type out key = ssh.SSHKey(pubkey, strict_mode=False, skip_option_parsing=True) diff --git a/ttadmin/users/models.py b/ttadmin/users/models.py index bcfdf50..5b42168 100644 --- a/ttadmin/users/models.py +++ b/ttadmin/users/models.py @@ -152,13 +152,25 @@ class Townie(User): return content + def rename_on_disk(self, old_username): + """Assuming that this instance has a new name set, renames this user on + disk with self.username.""" + error = _guarded_run([ + 'sudo', + '/tilde/bin/rename_user.py', + old_username, + self.username]) + if error: + logging.error(error) + return + logging.info('Renamed {} to {}'.format(old_username, self.username)) + class Pubkey(Model): key_type = CharField(max_length=50, blank=False, null=False, - choices=SSH_TYPE_CHOICES, - ) + choices=SSH_TYPE_CHOICES) key = TextField(blank=False, null=False) townie = ForeignKey(Townie) @@ -188,11 +200,16 @@ def on_townie_pre_save(sender, instance, **kwargs): existing = existing[0] - if not existing.reviewed and instance.reviewed == True: + # See if we need to create this user on disk. + if not existing.reviewed and instance.reviewed is True: instance.create_on_disk() instance.send_welcome_email() instance.write_authorized_keys() + # See if this user needs a rename on disk + if existing.username != instance.username: + instance.rename_on_disk(existing.username) + def _guarded_run(cmd_args, **run_args): """Given a list of args representing a command invocation as well as var @@ -213,9 +230,6 @@ def _guarded_run(cmd_args, **run_args): # things to consider: -# * what happens when a user wants their name changed? -# * it looks like usermod -l and a mv of the home dir can change a user's username. -# * would hook this into the pre_save signal to note a username change # * 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 @@ -225,7 +239,3 @@ def _guarded_run(cmd_args, **run_args): # think I can ignore it. # * what happens when a user needs to be banned? # * the Townie should be deleted via post_delete signal -# * what are things about a user that might change in django and require changes on disk? -# * username -# * displayname (only if i start using this?) -# * ssh key