this command is used to exchange a town invite token for a user account. it is
responsible for:
1. accepting and validating an invite token generated by the `review` command
2. accepting and validating a new user's username choice (ie enforcing rules and checking for dupes)
3. accepting and validating a user's email for use in account recovery (defaulting to an email embedded in the invite token)
4. accepting and validating a display name
5. asking what shell they'd like
6. accepting and validating a user's public ssh key
upon receipt of these things a user account is created. if it fails, the user
is told about the failure and told to email root@tilde.town for guidance; us
admins get a local mail about the problem.
upon successful creation, `welcome` prints a message on STDOUT suggesting how to log in then quits.
It is risky to let `welcome` create users but no riskier at a high level than the Django admin we had. I can re-use the sudoers trick I did there for the `welcome` user.
## an invite token
an invite token consists of two pieces that are then base64 encoded. the first piece is a random string of 30 characters (alphanumeric and symbols except space) and the second is an email address the invite was sent to; they are separated by a space.
A frustrating hurdle is that `welcome`, just like `ttadmin`, has to write a keyfile that is perms 600 for the new user. This is annoying as shit and requires running `sudo` as the new user. In the old python code:
```python
def write_authorized_keys(self):
# Write out authorized_keys file
# Why is this a call out to a python script? There's no secure way with
# sudoers to allow this code to write to a file; if this code was to be
# compromised, the ability to write arbitrary files with sudo is a TKO.
# By putting the ssh key file creation into its own script, we can just
# give sudo access for that one command to this code.
#
# We could put the other stuff from here into that script and then only
# grant sudo for the script, but then we're moving code out of this
# virtual-env contained, maintainable thing into a script. it's my
# preference to have the script be as minimal as possible.