@@ -66,24 +66,32 @@ def authenticate(self, username=None, password=None):
6666# Two regular django views to interact with the login system
6767####
6868
69+
6970# Handle login requests by sending them off to the main site
7071def login (request ):
71- if ' next' in request .GET :
72+ if " next" in request .GET :
7273 # Put together an url-encoded dict of parameters we're getting back,
7374 # including a small nonce at the beginning to make sure it doesn't
7475 # encrypt the same way every time.
75- s = "t=%s&%s" % (int (time .time ()), urlencode ({'r' : request .GET [' next' ]}))
76+ s = "t=%s&%s" % (int (time .time ()), urlencode ({"r" : request .GET [" next" ]}))
7677 # Now encrypt it
7778 r = Random .new ()
7879 iv = r .read (16 )
79- encryptor = AES .new (SHA .new (settings .SECRET_KEY .encode ('ascii' )).digest ()[:16 ], AES .MODE_CBC , iv )
80- cipher = encryptor .encrypt (s .encode ('ascii' ) + b' ' * (16 - (len (s ) % 16 ))) # pad to 16 bytes
81-
82- return HttpResponseRedirect ("%s?d=%s$%s" % (
83- settings .PGAUTH_REDIRECT ,
84- base64 .b64encode (iv , b"-_" ).decode ('utf8' ),
85- base64 .b64encode (cipher , b"-_" ).decode ('utf8' ),
86- ))
80+ encryptor = AES .new (
81+ SHA .new (settings .SECRET_KEY .encode ("ascii" )).digest ()[:16 ], AES .MODE_CBC , iv
82+ )
83+ cipher = encryptor .encrypt (
84+ s .encode ("ascii" ) + b" " * (16 - (len (s ) % 16 ))
85+ ) # pad to 16 bytes
86+
87+ return HttpResponseRedirect (
88+ "%s?d=%s$%s"
89+ % (
90+ settings .PGAUTH_REDIRECT ,
91+ base64 .b64encode (iv , b"-_" ).decode ("utf8" ),
92+ base64 .b64encode (cipher , b"-_" ).decode ("utf8" ),
93+ )
94+ )
8795 else :
8896 return HttpResponseRedirect (settings .PGAUTH_REDIRECT )
8997
@@ -99,21 +107,27 @@ def logout(request):
99107# Receive an authentication response from the main website and try
100108# to log the user in.
101109def auth_receive (request ):
102- if 's' in request .GET and request .GET ['s' ] == "logout" :
110+ if "s" in request .GET and request .GET ["s" ] == "logout" :
103111 # This was a logout request
104- return HttpResponseRedirect ('/' )
112+ return HttpResponseRedirect ("/" )
105113
106- if 'i' not in request .GET :
114+ if "i" not in request .GET :
107115 return HttpResponse ("Missing IV in url!" , status = 400 )
108- if 'd' not in request .GET :
116+ if "d" not in request .GET :
109117 return HttpResponse ("Missing data in url!" , status = 400 )
110118
111119 # Set up an AES object and decrypt the data we received
112120 try :
113- decryptor = AES .new (base64 .b64decode (settings .PGAUTH_KEY ),
114- AES .MODE_CBC ,
115- base64 .b64decode (str (request .GET ['i' ]), "-_" ))
116- s = decryptor .decrypt (base64 .b64decode (str (request .GET ['d' ]), "-_" )).rstrip (b' ' ).decode ('utf8' )
121+ decryptor = AES .new (
122+ base64 .b64decode (settings .PGAUTH_KEY ),
123+ AES .MODE_CBC ,
124+ base64 .b64decode (str (request .GET ["i" ]), "-_" ),
125+ )
126+ s = (
127+ decryptor .decrypt (base64 .b64decode (str (request .GET ["d" ]), "-_" ))
128+ .rstrip (b" " )
129+ .decode ("utf8" )
130+ )
117131 except UnicodeDecodeError :
118132 return HttpResponse ("Badly encoded data found" , 400 )
119133 except Exception :
@@ -126,23 +140,23 @@ def auth_receive(request):
126140 return HttpResponse ("Invalid encrypted data received." , status = 400 )
127141
128142 # Check the timestamp in the authentication
129- if ( int (data ['t' ][0 ]) < time .time () - 10 ) :
143+ if int (data ["t" ][0 ]) < time .time () - 10 :
130144 return HttpResponse ("Authentication token too old." , status = 400 )
131145
132146 # Update the user record (if any)
133147 try :
134- user = User .objects .get (username = data ['u' ][0 ])
148+ user = User .objects .get (username = data ["u" ][0 ])
135149 # User found, let's see if any important fields have changed
136150 changed = []
137- if user .first_name != data ['f' ][0 ]:
138- user .first_name = data ['f' ][0 ]
139- changed .append (' first_name' )
140- if user .last_name != data ['l' ][0 ]:
141- user .last_name = data ['l' ][0 ]
142- changed .append (' last_name' )
143- if user .email != data ['e' ][0 ]:
144- user .email = data ['e' ][0 ]
145- changed .append (' email' )
151+ if user .first_name != data ["f" ][0 ]:
152+ user .first_name = data ["f" ][0 ]
153+ changed .append (" first_name" )
154+ if user .last_name != data ["l" ][0 ]:
155+ user .last_name = data ["l" ][0 ]
156+ changed .append (" last_name" )
157+ if user .email != data ["e" ][0 ]:
158+ user .email = data ["e" ][0 ]
159+ changed .append (" email" )
146160 if changed :
147161 user .save (update_fields = changed )
148162 except User .DoesNotExist :
@@ -152,8 +166,9 @@ def auth_receive(request):
152166 # the database with a different userid. Instead of trying to
153167 # somehow fix that live, give a proper error message and
154168 # have somebody look at it manually.
155- if User .objects .filter (email = data ['e' ][0 ]).exists ():
156- return HttpResponse ("""A user with email %s already exists, but with
169+ if User .objects .filter (email = data ["e" ][0 ]).exists ():
170+ return HttpResponse (
171+ """A user with email %s already exists, but with
157172a different username than %s.
158173
159174This is almost certainly caused by some legacy data in our database.
@@ -162,26 +177,30 @@ def auth_receive(request):
162177for you.
163178
164179We apologize for the inconvenience.
165- """ % (data ['e' ][0 ], data ['u' ][0 ]), content_type = 'text/plain' )
166-
167- if getattr (settings , 'PGAUTH_CREATEUSER_CALLBACK' , None ):
168- res = getattr (settings , 'PGAUTH_CREATEUSER_CALLBACK' )(
169- data ['u' ][0 ],
170- data ['e' ][0 ],
171- ['f' ][0 ],
172- data ['l' ][0 ],
180+ """
181+ % (data ["e" ][0 ], data ["u" ][0 ]),
182+ content_type = "text/plain" ,
183+ )
184+
185+ if getattr (settings , "PGAUTH_CREATEUSER_CALLBACK" , None ):
186+ res = getattr (settings , "PGAUTH_CREATEUSER_CALLBACK" )(
187+ data ["u" ][0 ],
188+ data ["e" ][0 ],
189+ ["f" ][0 ],
190+ data ["l" ][0 ],
173191 )
174192 # If anything is returned, we'll return that as our result.
175193 # If None is returned, it means go ahead and create the user.
176194 if res :
177195 return res
178196
179- user = User (username = data ['u' ][0 ],
180- first_name = data ['f' ][0 ],
181- last_name = data ['l' ][0 ],
182- email = data ['e' ][0 ],
183- password = 'setbypluginnotasha1' ,
184- )
197+ user = User (
198+ username = data ["u" ][0 ],
199+ first_name = data ["f" ][0 ],
200+ last_name = data ["l" ][0 ],
201+ email = data ["e" ][0 ],
202+ password = "setbypluginnotasha1" ,
203+ )
185204 user .save ()
186205
187206 auth_user_created_from_upstream .send (sender = auth_receive , user = user )
@@ -193,47 +212,53 @@ def auth_receive(request):
193212 django_login (request , user )
194213
195214 # Signal that we have information about this user
196- auth_user_data_received .send (sender = auth_receive , user = user , userdata = {
197- 'secondaryemails' : data ['se' ][0 ].split (',' ) if 'se' in data else []
198- })
215+ auth_user_data_received .send (
216+ sender = auth_receive ,
217+ user = user ,
218+ userdata = {"secondaryemails" : data ["se" ][0 ].split ("," ) if "se" in data else []},
219+ )
199220
200221 # Finally, check of we have a data package that tells us where to
201222 # redirect the user.
202- if 'd' in data :
203- (ivs , datas ) = data ['d' ][0 ].split ('$' )
204- decryptor = AES .new (SHA .new (settings .SECRET_KEY .encode ('ascii' )).digest ()[:16 ],
205- AES .MODE_CBC ,
206- base64 .b64decode (ivs , b"-_" ))
207- s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (b' ' ).decode ('utf8' )
223+ if "d" in data :
224+ (ivs , datas ) = data ["d" ][0 ].split ("$" )
225+ decryptor = AES .new (
226+ SHA .new (settings .SECRET_KEY .encode ("ascii" )).digest ()[:16 ],
227+ AES .MODE_CBC ,
228+ base64 .b64decode (ivs , b"-_" ),
229+ )
230+ s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (b" " ).decode ("utf8" )
208231 try :
209232 rdata = parse_qs (s , strict_parsing = True )
210233 except ValueError :
211234 return HttpResponse ("Invalid encrypted data received." , status = 400 )
212- if 'r' in rdata :
235+ if "r" in rdata :
213236 # Redirect address
214- return HttpResponseRedirect (rdata ['r' ][0 ])
237+ return HttpResponseRedirect (rdata ["r" ][0 ])
215238 # No redirect specified, see if we have it in our settings
216- if hasattr (settings , ' PGAUTH_REDIRECT_SUCCESS' ):
239+ if hasattr (settings , " PGAUTH_REDIRECT_SUCCESS" ):
217240 return HttpResponseRedirect (settings .PGAUTH_REDIRECT_SUCCESS )
218- return HttpResponse ("Authentication successful, but don't know where to redirect!" , status = 500 )
241+ return HttpResponse (
242+ "Authentication successful, but don't know where to redirect!" , status = 500
243+ )
219244
220245
221246# Receive API calls from upstream, such as push changes to users
222247@csrf_exempt
223248def auth_api (request ):
224- if ' X-pgauth-sig' not in request .headers :
249+ if " X-pgauth-sig" not in request .headers :
225250 return HttpResponse ("Missing signature header!" , status = 400 )
226251
227252 try :
228- sig = base64 .b64decode (request .headers [' X-pgauth-sig' ])
253+ sig = base64 .b64decode (request .headers [" X-pgauth-sig" ])
229254 except Exception :
230255 return HttpResponse ("Invalid signature header!" , status = 400 )
231256
232257 try :
233258 h = hmac .digest (
234259 base64 .b64decode (settings .PGAUTH_KEY ),
235260 msg = request .body ,
236- digest = ' sha512' ,
261+ digest = " sha512" ,
237262 )
238263 if not hmac .compare_digest (h , sig ):
239264 return HttpResponse ("Invalid signature!" , status = 401 )
@@ -261,26 +286,38 @@ def _conditionally_update_record(rectype, recordkey, structkey, fieldmap, struct
261286 return None
262287
263288 # Process the received structure
264- if pushstruct .get (' type' , None ) == ' update' :
289+ if pushstruct .get (" type" , None ) == " update" :
265290 # Process updates!
266291 with transaction .atomic ():
267- for u in pushstruct .get (' users' , []):
292+ for u in pushstruct .get (" users" , []):
268293 user = _conditionally_update_record (
269294 User ,
270- 'username' , 'username' ,
295+ "username" ,
296+ "username" ,
271297 {
272- ' firstname' : ' first_name' ,
273- ' lastname' : ' last_name' ,
274- ' email' : ' email' ,
298+ " firstname" : " first_name" ,
299+ " lastname" : " last_name" ,
300+ " email" : " email" ,
275301 },
276302 u ,
277303 )
278304
279305 # Signal that we have information about this user (only if it exists)
280306 if user :
281- auth_user_data_received .send (sender = auth_api , user = user , userdata = {
282- k : u [k ] for k in u .keys () if k not in ['firstname' , 'lastname' , 'email' , ]
283- })
307+ auth_user_data_received .send (
308+ sender = auth_api ,
309+ user = user ,
310+ userdata = {
311+ k : u [k ]
312+ for k in u .keys ()
313+ if k
314+ not in [
315+ "firstname" ,
316+ "lastname" ,
317+ "email" ,
318+ ]
319+ },
320+ )
284321
285322 return HttpResponse ("OK" , status = 200 )
286323
@@ -297,24 +334,24 @@ def user_search(searchterm=None, userid=None):
297334 # 10 seconds is already quite long.
298335 socket .setdefaulttimeout (10 )
299336 if userid :
300- q = {'u' : userid }
337+ q = {"u" : userid }
301338 else :
302- q = {'s' : searchterm }
339+ q = {"s" : searchterm }
303340
304341 r = requests .get (
305- ' {0}search/' .format (settings .PGAUTH_REDIRECT ),
342+ " {0}search/" .format (settings .PGAUTH_REDIRECT ),
306343 params = q ,
307344 )
308345 if r .status_code != 200 :
309346 return []
310347
311- (ivs , datas ) = r .text .encode (' utf8' ).split (b'&' )
348+ (ivs , datas ) = r .text .encode (" utf8" ).split (b"&" )
312349
313350 # Decryption time
314- decryptor = AES .new (base64 . b64decode ( settings . PGAUTH_KEY ),
315- AES .MODE_CBC ,
316- base64 . b64decode ( ivs , "-_" ) )
317- s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (b' ' ).decode (' utf8' )
351+ decryptor = AES .new (
352+ base64 . b64decode ( settings . PGAUTH_KEY ), AES .MODE_CBC , base64 . b64decode ( ivs , "-_" )
353+ )
354+ s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (b" " ).decode (" utf8" )
318355 j = json .loads (s )
319356
320357 return j
@@ -324,22 +361,24 @@ def user_search(searchterm=None, userid=None):
324361def subscribe_to_user_changes (userid ):
325362 socket .setdefaulttimeout (10 )
326363
327- body = json .dumps ({
328- 'u' : userid ,
329- })
364+ body = json .dumps (
365+ {
366+ "u" : userid ,
367+ }
368+ )
330369
331370 h = hmac .digest (
332371 base64 .b64decode (settings .PGAUTH_KEY ),
333- msg = bytes (body , ' utf-8' ),
334- digest = ' sha512' ,
372+ msg = bytes (body , " utf-8" ),
373+ digest = " sha512" ,
335374 )
336375
337376 # Ignore the result code, just post it
338377 requests .post (
339- ' {0}subscribe/' .format (settings .PGAUTH_REDIRECT ),
378+ " {0}subscribe/" .format (settings .PGAUTH_REDIRECT ),
340379 data = body ,
341380 headers = {
342- ' X-pgauth-sig' : base64 .b64encode (h ),
381+ " X-pgauth-sig" : base64 .b64encode (h ),
343382 },
344383 )
345384
@@ -359,15 +398,15 @@ def user_import(uid):
359398
360399 u = u [0 ]
361400
362- if User .objects .filter (username = u ['u' ]).exists ():
401+ if User .objects .filter (username = u ["u" ]).exists ():
363402 raise Exception ("User already exists" )
364403
365404 u = User (
366- username = u ['u' ],
367- first_name = u ['f' ],
368- last_name = u ['l' ],
369- email = u ['e' ],
370- password = ' setbypluginnotsha1' ,
405+ username = u ["u" ],
406+ first_name = u ["f" ],
407+ last_name = u ["l" ],
408+ email = u ["e" ],
409+ password = " setbypluginnotsha1" ,
371410 )
372411 u .save ()
373412
0 commit comments