2016-11-30 07:48:02 +00:00
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
2016-12-01 06:49:06 +00:00
from . models import Townie , SSH_TYPE_CHOICES
2016-12-20 07:09:09 +00:00
from common . forms import CaptchaField , throttler
submission_throttle = { }
throttle_submission = throttler ( submission_throttle )
2016-12-19 05:28:16 +00:00
2016-11-30 07:48:02 +00:00
USERNAME_RE = re . compile ( r ' [a-z][a-z0-9_]+ ' )
2017-01-17 07:49:16 +00:00
USERNAME_MIN_LENGTH = 3
2016-11-30 07:48:02 +00:00
DISPLAY_NAME_RE = re . compile ( r " [a-zA-Z0-9_ \ - ' ]+ " )
DISPLAY_MIN_LENGTH = 2
2016-12-19 23:22:06 +00:00
2016-11-30 07:48:02 +00:00
def validate_username ( username ) :
if len ( username ) < USERNAME_MIN_LENGTH :
raise ValidationError ( ' Username too short. ' )
if not USERNAME_RE . match ( username ) :
2017-01-17 06:10:46 +00:00
raise ValidationError ( ' Username must be all lowercase, start with a letter, and only use the _ special character ' )
2016-12-01 06:49:06 +00:00
duplicate = Townie . objects . filter ( username = username ) . count ( )
if duplicate > 0 :
raise ValidationError ( ' Username already in use :( ' )
2016-11-30 07:48:02 +00:00
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 ) :
2016-11-30 08:32:53 +00:00
# TODO see if I can get the type out
2016-11-30 07:48:02 +00:00
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 ) )
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 % o ptional. 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. ' )
2016-12-19 05:28:16 +00:00
captcha = CaptchaField ( )
2016-11-30 07:48:02 +00:00
pubkey = CharField (
widget = Textarea ,
validators = ( validate_pubkey , ) ,
label = ' SSH public key ' ,
2017-02-24 06:10:31 +00:00
help_text = ' if this is not a thing you are familiar with, that \' s okay! you can make one <a href= " /users/keymachine " >here</a> or read <a href= " https://tilde.town/~wiki/ssh.html " >our guide</a> to learn more. ' )
2016-11-30 07:48:02 +00:00
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. ' )
2016-12-20 07:09:09 +00:00
throttle_submission ( self . cleaned_data [ ' email ' ] )
2016-11-30 07:48:02 +00:00
return result