progress on form

pull/1/head
nathaniel smith 2016-11-29 23:48:02 -08:00
parent f1fc5f4cb8
commit 2d8abd3577
4 changed files with 133 additions and 41 deletions

View File

@ -0,0 +1,98 @@
from random import shuffle
import re
from django.core.exceptions import ValidationError
from django.forms import Form, CharField, EmailField, Textarea, ChoiceField, BooleanField
import sshpubkeys as ssh
from .models import SSH_TYPE_CHOICES
USERNAME_RE = re.compile(r'[a-z][a-z0-9_]+')
USERNAME_MIN_LENGTH = 4
DISPLAY_NAME_RE = re.compile(r"[a-zA-Z0-9_\-']+")
DISPLAY_MIN_LENGTH = 2
# >_>
CAPTCHA_CHOICES = [('two', 'zorp borp'),
('three', 'quop bop'),
('four', 'NO, I AM NOT A ROBOT'),
('five', 'crackle zop'),
('six', '*rusty screech*'),
('seven', 'mother, give me legs')]
shuffle(CAPTCHA_CHOICES)
CAPTCHA_CHOICES.insert(0, ('one', 'beep boop'),)
NOT_A_ROBOT = 'four'
# <_<
def validate_username(username):
if len(username) < USERNAME_MIN_LENGTH:
raise ValidationError('Username too short.')
if not USERNAME_RE.match(username):
raise ValidationError('Username must be all lowercase, start with a letter, and only use the _ special charcter')
def validate_displayname(display_name):
if len(display_name) < DISPLAY_MIN_LENGTH:
raise ValidationError('Display name too short.')
if not DISPLAY_NAME_RE.match(display_name):
raise ValidationError("Valid characters: a-z, A-Z, 0-9, -, _, and '.")
def validate_pubkey(pubkey):
key = ssh.SSHKey(pubkey, strict_mode=False, skip_option_parsing=True)
try:
key.parse()
except ssh.InvalidKeyException as e:
raise ValidationError('Could not validate key: {}'.format(e))
except NotImplementedError as e:
raise ValidationError('Invalid key type')
except Exception as e:
raise ValidationError('unknown error: {}'.format(e))
def validate_captcha(captcha):
if captcha != NOT_A_ROBOT:
raise ValidationError('Are you sure you are not a robot?')
class TownieForm(Form):
username = CharField(
validators=(validate_username,),
help_text='lowercase and no spaces. underscore ok',
label='username')
email = EmailField(
help_text='only used to message you about your account and nothing else.',
label='e-mail')
displayname = CharField(
validators=(validate_displayname,),
help_text='100% optional. pseudonyms welcome.',
label='display name',
required=False)
reasons = CharField(
widget=Textarea,
required=False,
label='what interests you about tilde.town?',
help_text='This is a totally optional place for you to tell us what excites you about getting a ~ account. This is mainly just so we can all feel warm fuzzies.')
captcha = ChoiceField(
choices=CAPTCHA_CHOICES,
label='are you a robot?',
help_text='pick the response that indicates whether or not you are a robot.',
validators=(validate_captcha,)
)
pubkey = CharField(
widget=Textarea,
validators=(validate_pubkey,),
label='SSH public key',
help_text='if this is not a thing you are familiar with, that\'s okay! check out <a href="https://tilde.town/~wiki/ssh.html">our guide</a> to learn how to get one of these.')
pubkey_type = ChoiceField(
choices=SSH_TYPE_CHOICES,
label='SSH public key type',
help_text="unless you know what you're doing you can leave this be.")
aup = BooleanField(
label='i super agree to our acceptable use policy',
help_text='please read our <a href="https://tilde.town/~wiki/conduct.html">code of conduct</a> and click this box if you agree.')
def clean(self):
result = super().clean()
if self.errors:
raise ValidationError('oops, looks like there were some problems below.')
return result

View File

@ -1,19 +1,24 @@
import re
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
SSH_TYPE_CHOICES = (
('ssh-rsa', 'ssh-rsa',),
('ssh-dss', 'ssh-dss',),
)
class Townie(User):
"""Both an almost normal Django User as well as an abstraction over a
system user."""
pubkey = TextField(blank=False, null=False)
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,

View File

@ -1,9 +1,9 @@
from django.conf.urls import url
from .views import UserSignupView
from .views import SignupView, ThanksView
app_name = 'users'
urlpatterns = [
url(r'^signup/?$', UserSignupView.as_view(), name='signup'),
url(r'^signup/?$', SignupView.as_view(), name='signup'),
url(r'^thanks/?$', ThanksView.as_view(), name='thanks'),
]

View File

@ -1,48 +1,37 @@
import re
from django.core.exceptions import ValidationError
from django.forms import Form, CharField, EmailField, Textarea, ChoiceField, BooleanField
from django.http import HttpResponse
from django.shortcuts import redirect
from django.views.generic import TemplateView
from django.views.generic.edit import FormView
from django.urls import reverse
from .models import Townie, SSH_TYPE_CHOICES
from .forms import TownieForm
from .models import Townie
# TODO validation functions for final request validation and live js validation
# I refuse to duplicate the logic for validation on the front-end and am going
# to accept round-trip validation costs with long-term caching.
class SignupView(FormView):
form_class = TownieForm
template_name = 'users/signup.html'
# TODO reverse
success_url = '/thanks'
class UserSignupView(TemplateView):
template_name = 'ttadmin/signup.html'
def form_valid(self, form):
def get_context_data(self):
ctx = super().get_context_data()
ctx['ssh_type_choices'] = SSH_TYPE_CHOICES
return ctx
#t = Townie(
# username=username,
# displayname=displayname,
# pubkey=pubkey,
# email=email,
#)
def post(self, request):
print(request.POST)
# TODO validate
username = request.POST.get('username')
#t.set_unusable_password()
#t.save()
displayname = request.POST.get('displayname')
if displayname is None:
displayname = username
else:
# TODO validate
pass
# TODO validate
pubkey = request.POST.get('pubkey')
# TODO validate
email = request.POST.get('email')
t = Townie(
username=username,
displayname=displayname,
pubkey=pubkey,
email=email,
)
t.set_unusable_password()
t.save()
return super().form_valid(form)
return HttpResponse('LOLOLOLOL')
# TODO add template for this once i've fixed template directories
class ThanksView(TemplateView):
template_name = 'users/thanks.html'