Merge pull request #28 from tildetown/rename-users

Support renaming users
feature/enhanced-ticket-view
Nate Smith 2018-02-24 00:22:13 -08:00 committed by GitHub
commit 747f1e6f17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 13 deletions

View File

@ -17,6 +17,7 @@ _Being an adminstrative tool written in Django for <https://tilde.town>_.
* Python 3.5+ * Python 3.5+
* PostgreSQL 9+ * PostgreSQL 9+
* Ubuntu or Debian
## Installation / setup ## Installation / setup

0
scripts/create_keyfile.py 100644 → 100755
View File

View File

@ -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))

View File

@ -15,10 +15,13 @@
* create ttadmin user * create ttadmin user
* ttadmin db user (or just rely on ident..?) / database created * ttadmin db user (or just rely on ident..?) / database created
* copy `create_keyfile.py` from `scripts/` and put it in `/opt/bin/`. * copy `create_keyfile.py` from `scripts/` and put it in `/opt/bin/`.
* `chmod o+x /opt/bin/create_keyfile.py`` * copy `rename_user.py` from `scripts/` and put it in `/tilde/bin/`.
* `chmod u+x /opt/bin/create_keyfile.py``
* add to sudoers: * 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 * 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 * run django app as wsgi container through gunicorn as the ttadmin user with venv active

View File

@ -34,6 +34,7 @@ def validate_displayname(display_name):
if not DISPLAY_NAME_RE.match(display_name): if not DISPLAY_NAME_RE.match(display_name):
raise ValidationError("Valid characters: a-z, A-Z, 0-9, -, _, and '.") raise ValidationError("Valid characters: a-z, A-Z, 0-9, -, _, and '.")
def validate_pubkey(pubkey): def validate_pubkey(pubkey):
# TODO see if I can get the type out # TODO see if I can get the type out
key = ssh.SSHKey(pubkey, strict_mode=False, skip_option_parsing=True) key = ssh.SSHKey(pubkey, strict_mode=False, skip_option_parsing=True)

View File

@ -152,13 +152,25 @@ class Townie(User):
return content 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): class Pubkey(Model):
key_type = CharField(max_length=50, key_type = CharField(max_length=50,
blank=False, blank=False,
null=False, null=False,
choices=SSH_TYPE_CHOICES, choices=SSH_TYPE_CHOICES)
)
key = TextField(blank=False, null=False) key = TextField(blank=False, null=False)
townie = ForeignKey(Townie) townie = ForeignKey(Townie)
@ -188,11 +200,16 @@ def on_townie_pre_save(sender, instance, **kwargs):
existing = existing[0] 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.create_on_disk()
instance.send_welcome_email() instance.send_welcome_email()
instance.write_authorized_keys() 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): def _guarded_run(cmd_args, **run_args):
"""Given a list of args representing a command invocation as well as var """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: # 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? # * what happens when a user is marked as not reviewed?
# * does this signal user deletion? Or does literal Townie deletion signal # * 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 # "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. # think I can ignore it.
# * what happens when a user needs to be banned? # * what happens when a user needs to be banned?
# * the Townie should be deleted via post_delete signal # * 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