Merge pull request #1 from nathanielksmith/master

support multiple pubkeys, misc
pull/16/head
Nathaniel Smith 2017-01-13 22:47:33 -08:00 committed by GitHub
commit 871474ab6d
6 changed files with 95 additions and 23 deletions

View File

@ -4,10 +4,11 @@ _Being an adminstrative and user-signup tool for [https://tilde.town]_.
## Features
(None of these are actually implemented yet)
* User signup form with client-side key generation
* User account management
* User signup form (✓)
* with client-side key generation (only server-side key **validation** at this point)
* Guestbook (✓)
* Helpdesk (✓)
* User account management (admin only)
* Start/stop services
* Cost reporting using AWS
* Status monitoring

View File

@ -1,6 +1,16 @@
from django.contrib import admin
from .models import Townie
from django.contrib.auth.models import User
from django.contrib.auth.models import Group
from .models import Townie, Pubkey
admin.site.unregister(User)
admin.site.unregister(Group)
class PubkeyInline(admin.TabularInline):
model = Pubkey
@admin.register(Townie)
class TownieAdmin(admin.ModelAdmin):
inlines = [PubkeyInline]
pass

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2017-01-13 21:26
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0006_townie_reasons'),
]
operations = [
migrations.AlterModelOptions(
name='townie',
options={'verbose_name': 'Townie', 'verbose_name_plural': 'Townies'},
),
migrations.RemoveField(
model_name='townie',
name='pubkey_type',
),
]

View File

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2017-01-13 21:28
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0007_auto_20170113_2126'),
]
operations = [
migrations.CreateModel(
name='Pubkey',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('key_type', models.CharField(choices=[('ssh-rsa', 'ssh-rsa'), ('ssh-dss', 'ssh-dss')], max_length=15)),
('key', models.TextField()),
],
),
migrations.RemoveField(
model_name='townie',
name='pubkey',
),
migrations.AddField(
model_name='pubkey',
name='townie',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Townie'),
),
]

View File

@ -1,9 +1,10 @@
import re
from django.db.models import Model
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.db.models import TextField, BooleanField, CharField
from django.db.models import TextField, BooleanField, CharField, ForeignKey
SSH_TYPE_CHOICES = (
@ -15,24 +16,13 @@ SSH_TYPE_CHOICES = (
class Townie(User):
"""Both an almost normal Django User as well as an abstraction over a
system user."""
pubkey = TextField(blank=False, null=False)
class Meta:
verbose_name = 'Townie'
verbose_name_plural = 'Townies'
shell = CharField(max_length=50, default="/bin/bash")
reviewed = BooleanField(default=False)
reasons = TextField(blank=True, null=False, default='')
displayname = CharField(max_length=100, blank=False, null=False)
pubkey_type = CharField(max_length=15,
blank=False,
null=False,
choices=SSH_TYPE_CHOICES)
@property
def home_path(self):
return "/home/{}".format(self.username)
def accept(self):
"""Sets self.pending to False. Indicates the user has been signed up
after review."""
self.pending = False
# TODO consider a generic ensure method that syncs this model with the
# system. there will likely be things besides shell that we want to keep
@ -42,6 +32,17 @@ class Townie(User):
is."""
raise NotImplementedError()
class Pubkey(Model):
key_type = CharField(max_length=15,
blank=False,
null=False,
choices=SSH_TYPE_CHOICES,
)
key = TextField(blank=False, null=False)
townie = ForeignKey(Townie)
@receiver(post_save, sender=Townie)
def sync_system_state(sender, instance, created, **kwargs):
if created:

View File

@ -1,6 +1,7 @@
import re
from django.core.exceptions import ValidationError
from django.db import transaction
from django.forms import Form, CharField, EmailField, Textarea, ChoiceField, BooleanField
from django.http import HttpResponse
from django.shortcuts import redirect
@ -8,21 +9,24 @@ from django.views.generic import TemplateView
from django.views.generic.edit import FormView
from .forms import TownieForm
from .models import Townie
from .models import Townie, Pubkey
class SignupView(FormView):
form_class = TownieForm
template_name = 'users/signup.html'
@transaction.atomic
def form_valid(self, form):
del form.cleaned_data['captcha']
del form.cleaned_data['aup']
pubkey = Pubkey(key=form.cleaned_data.pop('pubkey'),
key_type=form.cleaned_data.pop('pubkey_type'))
t = Townie(**form.cleaned_data)
t.set_unusable_password()
t.save()
pubkey.townie = t
pubkey.save()
return redirect('users:thanks')