forked from rggibson/pb-tracker
/
signup.py
241 lines (214 loc) · 9.44 KB
/
signup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# signup.py
# Author: Richard Gibson
#
# Handles user registration and creates runners.Runners entities. Upon
# successful signup, the user is redirected to his or her previous page
# stored in the 'from' query parameter.
#
import handler
import runners
import re
import util
import hashlib
import json
from pytz.gae import pytz
USER_RE = re.compile( r"^[a-zA-Z0-9_-]{1,20}$" )
def valid_username( username ):
return USER_RE.match( username )
PASS_RE = re.compile( r"^.{3,20}$" )
def valid_password( password ):
return PASS_RE.match( password )
EMAIL_RE = re.compile( r"^[\S]+@[\S]+\.[\S]+$" )
def valid_email( email ):
return EMAIL_RE.match( email )
class Signup( handler.Handler ):
def get( self ):
user = self.get_user( )
if user == self.OVER_QUOTA_ERROR:
self.error( 403 )
self.render( "403.html" )
return
return_url = self.request.get( 'from' )
if not return_url:
return_url = "/"
elif user is not None and user.is_mod:
# Mod is editing a user's profile, possibly his or her own
username_code = return_url.split( '/' )[ -1 ]
user = self.get_runner( username_code )
if user == self.OVER_QUOTA_ERROR:
self.error( 403 )
self.render( "403.html" )
return
if user is not None:
# Editing profile
params = dict( user=user,
youtube=user.youtube,
twitch=user.twitch,
return_url=return_url )
if user.hitbox is not None:
params['hitbox'] = user.hitbox
else:
params['hitbox'] = ''
if user.twitter:
params['twitter'] = '@' + user.twitter
if user.gravatar:
params['gravatar'] = '<private email>'
params['gravatar_url'] = util.get_gravatar_url( user.gravatar,
30 )
if user.timezone is not None:
params['timezone'] = user.timezone
self.render( "signup.html", timezones=pytz.common_timezones,
**params )
else:
# New user
self.render( "signup.html", return_url=return_url,
timezones=pytz.common_timezones )
def post( self ):
user = self.get_user( )
if user == self.OVER_QUOTA_ERROR:
self.error( 403 )
self.render( "403.html" )
return
username = self.request.get( 'username' )
password = self.request.get( 'password' )
verify = self.request.get( 'verify' )
twitter = self.request.get( 'twitter' )
if twitter[ 0:1 ] == '@':
twitter = twitter[ 1: ]
youtube = self.request.get( 'youtube' )
youtube = youtube.split( '/' )[ -1 ]
twitch = self.request.get( 'twitch' )
twitch = twitch.split( '/' )[ -1 ]
hitbox = self.request.get( 'hitbox' )
hitbox = hitbox.split( '/' )[ -1 ]
timezone = self.request.get( 'timezone' )
gravatar = self.request.get( 'gravatar' )
if user is not None:
username_code = util.get_code( user.username )
else:
username_code = util.get_code( username )
return_url = self.request.get( 'from' )
if not return_url:
return_url = "/"
elif user is not None and user.is_mod:
# Mod is editing a user's profile, possibly his or her own
username_code = return_url.split( '/' )[ -1 ]
user = self.get_runner( username_code )
if user == self.OVER_QUOTA_ERROR:
self.error( 403 )
self.render( "403.html" )
return
params = dict( user = user,
username = username,
password = password,
verify = verify,
twitter = twitter,
youtube = youtube,
twitch = twitch,
hitbox = hitbox,
gravatar = gravatar,
timezone = timezone,
return_url = return_url )
valid = True
if user is None and not valid_username( username ):
params['user_error'] = ( "Username must be between "
+ "1 and 20 alphanumeric, dash, or "
+ "underscore characters." )
valid = False
elif user is None:
# Check if username already exists
runner = self.get_runner( username_code )
if runner == self.OVER_QUOTA_ERROR:
self.error( 403 )
self.render( "403.html", user=user )
return
if runner is not None:
params['user_error'] = "That user already exists."
valid = False
if not valid_password( password ):
if user is None or len( password ) > 0:
params['pass_error'] = ( "Password must be between "
+ "3 and 20 characters." )
valid = False
if password != verify:
params['ver_error'] = "Passwords do not match."
valid = False
if gravatar != "" and not valid_email( gravatar ):
if( user is None or not user.gravatar
or gravatar != '<private email>' ):
params['gravatar_error'] = "That's not a valid email."
valid = False
if user is not None and gravatar == '<private email>':
params['gravatar_url'] = util.get_gravatar_url( user.gravatar,
30 )
if timezone != '' and timezone not in pytz.common_timezones:
params['timezone_error'] = "Invalid timezone."
valid = False
if not valid:
self.render( "signup.html", timezones=pytz.common_timezones,
**params )
return
if not user:
# Add a new runner to the database
runner = runners.Runners( username = username,
password = util.make_pw_hash(
username_code, password ),
twitter = twitter,
youtube = youtube,
twitch = twitch,
hitbox = hitbox,
timezone = timezone,
num_pbs = 0,
parent = runners.key(),
key_name = username_code )
if gravatar:
runner.gravatar = hashlib.md5( gravatar.lower( ) ).hexdigest( )
runner.put( )
# Update runner in memcache
self.update_cache_runner( username_code, runner )
# Update runnerlist in memcache. Note that this puts the runner
# at the end of the list, rather than in alphabetical order among
# those runners with 0 pbs. The runner will be sorted properly
# if the memcache gets flushed, which is good enough
runnerlist = self.get_runnerlist( no_refresh=True )
if runnerlist == self.OVER_QUOTA_ERROR:
self.update_cache_runnerlist( None )
elif runnerlist is not None:
runnerlist.append( dict( username = username,
username_code = username_code,
num_pbs = 0,
gravatar_url = util.get_gravatar_url(
runner.gravatar ) ) )
self.update_cache_runnerlist( runnerlist )
# Update runs for runner in memcache
self.update_cache_runlist_for_runner( username, [ ] )
self.login( username_code )
else:
# Editing the current user
if len( password ) > 0:
user.password = util.make_pw_hash( username_code, password )
user.twitter = twitter
user.youtube = youtube
user.twitch = twitch
user.hitbox = hitbox
user.timezone = timezone
if gravatar and gravatar != '<private email>':
user.gravatar = hashlib.md5( gravatar.lower( ) ).hexdigest( )
elif not gravatar:
user.gravatar = None
user.put( )
# Update user in memcache
self.update_cache_runner( username_code, user )
# Update runnerlist in memcache if gravatar updated
if gravatar != '<private email>':
runnerlist = self.get_runnerlist( no_refresh=True )
if runnerlist == self.OVER_QUOTA_ERROR:
self.update_cache_runnerlist( None )
elif runnerlist is not None:
for runnerdict in runnerlist:
if runnerdict['username'] == user.username:
runnerdict['gravatar_url'] = util.get_gravatar_url(
user.gravatar )
break
self.update_cache_runnerlist( runnerlist )
self.redirect( return_url )