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 ' )
2019-07-16 02:15:33 +00:00
duplicate = Townie . objects . filter ( username = username ) . exclude ( state = Townie . REJECTED ) . count ( )
2016-12-01 06:49:06 +00:00
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 ' . " )
2018-02-23 21:58:54 +00:00
2016-11-30 07:48:02 +00:00
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 ' )
2019-02-14 23:45:45 +00:00
2016-11-30 07:48:02 +00:00
email = EmailField (
help_text = ' only used to message you about your account and nothing else. ' ,
label = ' e-mail ' )
2019-02-14 23:45:45 +00:00
2016-11-30 07:48:02 +00:00
displayname = CharField (
validators = ( validate_displayname , ) ,
help_text = ' 100 % o ptional. pseudonyms welcome. ' ,
label = ' display name ' ,
required = False )
2019-02-14 23:45:45 +00:00
2019-04-16 01:23:35 +00:00
referral = CharField (
required = False ,
label = ' did a townie refer you? put their handle here. ' ,
help_text = " this is optional and just helps us when reviewing your application. " )
2016-11-30 07:48:02 +00:00
reasons = CharField (
widget = Textarea ,
2019-02-14 23:45:45 +00:00
required = True ,
2016-11-30 07:48:02 +00:00
label = ' what interests you about tilde.town? ' ,
2019-02-14 23:45:45 +00:00
help_text = """
What about this intentional community intrigues you and makes you want to be a part of it ?
""" .strip())
plans = CharField (
widget = Textarea ,
required = True ,
label = ' what sort of things do you want to do on tilde.town? ' ,
help_text = """
Do you want to socialize ? Make something ? Learn stuff ?
""" .strip())
socials = CharField (
widget = Textarea ,
required = False ,
label = ' where else are you online? ' ,
help_text = """ Optional, but if you ' re comfortable sharing with us some links to other online
spaces you ' re in (like twitter, mastodon, neocities, or whatever) we ' d love to get to know
you when reviewing your application .
""" .strip())
2016-12-19 05:28:16 +00:00
captcha = CaptchaField ( )
2019-02-14 23:45:45 +00:00
2016-11-30 07:48:02 +00:00
pubkey = CharField (
widget = Textarea ,
validators = ( validate_pubkey , ) ,
label = ' SSH public key ' ,
2019-01-18 21:08:45 +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/getting-started/ssh.html " >our guide</a> to learn more. ' )
2019-02-14 23:45:45 +00:00
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. " )
2019-02-14 23:45:45 +00:00
2016-11-30 07:48:02 +00:00
aup = BooleanField (
2019-02-14 23:45:45 +00:00
label = " i agree to the town ' s acceptable use policy " ,
2019-01-18 21:08:45 +00:00
help_text = ' please read our <a href= " https://tilde.town/wiki/conduct.html " >code of conduct</a> and click this box if you agree. ' )
2016-11-30 07:48:02 +00:00
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