def resetpwd(request): # Basic django password reset feature is completely broken. For example, it does not support # resetting passwords for users with "old hashes", which means they have no way to ever # recover. So implement our own, since it's quite the trivial feature. if request.method == "POST": try: u = User.objects.get(email__iexact=request.POST['email']) if u.password == OAUTH_PASSWORD_STORE: return HttpSimpleResponse(request, "Account error", "This account cannot change password as it's connected to a third party login site.") except User.DoesNotExist: log.info("Attempting to reset password of {0}, user not found".format(request.POST['email'])) return HttpResponseRedirect('/account/reset/done/') form = PgwebPasswordResetForm(data=request.POST) if form.is_valid(): log.info("Initiating password set from {0} for {1}".format(get_client_ip(request), form.cleaned_data['email'])) token = default_token_generator.make_token(u) send_template_mail( settings.ACCOUNTS_NOREPLY_FROM, u.email, 'Password reset for your postgresql.org account', 'account/password_reset_email.txt', { 'user': u, 'uid': urlsafe_base64_encode(force_bytes(u.pk)), 'token': token, }, ) return HttpResponseRedirect('/account/reset/done/') else: form = PgwebPasswordResetForm() return render_pgweb(request, 'account', 'account/password_reset.html', { 'form': form, })
def signup(request): if request.user.is_authenticated: return HttpSimpleResponse( request, "Account error", "You must log out before you can sign up for a new account") if request.method == 'POST': # Attempt to create user then, eh? form = SignupForm(get_client_ip(request), data=request.POST) if form.is_valid(): # Attempt to create the user here # XXX: Do we need to validate something else? log.info("Creating user for {0} from {1}".format( form.cleaned_data['username'], get_client_ip(request))) user = User.objects.create_user( form.cleaned_data['username'].lower(), form.cleaned_data['email'].lower(), last_login=datetime.now()) user.first_name = form.cleaned_data['first_name'] user.last_name = form.cleaned_data['last_name'] # generate a random value for password. It won't be possible to log in with it, but # it creates more entropy for the token generator (I think). user.password = generate_random_token() user.save() # Now generate a token token = default_token_generator.make_token(user) log.info("Generated token {0} for user {1} from {2}".format( token, form.cleaned_data['username'], get_client_ip(request))) # Generate an outgoing email send_template_mail( settings.ACCOUNTS_NOREPLY_FROM, form.cleaned_data['email'], 'Your new postgresql.org community account', 'account/new_account_email.txt', { 'uid': urlsafe_base64_encode(force_bytes(user.id)), 'token': token, 'user': user }) return HttpResponseRedirect('/account/signup/complete/') else: form = SignupForm(get_client_ip(request)) return render_pgweb( request, 'account', 'base/form.html', { 'form': form, 'formitemtype': 'Account', 'form_intro': """ To sign up for a free community account, enter your preferred userid and email address. Note that a community account is only needed if you want to submit information - all content is available for reading without an account. A confirmation email will be sent to the specified address, and once confirmed a password for the new account can be specified. """, 'savebutton': 'Sign up', 'operation': 'New', 'recaptcha': True, })
def changepwd(request): if hasattr(request.user, 'password') and request.user.password == OAUTH_PASSWORD_STORE: return HttpSimpleResponse(request, "Account error", "This account cannot change password as it's connected to a third party login site.") log.info("Initiating password change from {0}".format(get_client_ip(request))) return authviews.PasswordChangeView.as_view(template_name='account/password_change.html', success_url='/account/changepwd/done/')(request)
def vote(request, surveyid): surv = get_object_or_404(Survey, pk=surveyid) # Check that we have a valid answer number try: ansnum = int(request.POST['answer']) if ansnum < 1 or ansnum > 8: return HttpSimpleResponse(request, "Response error", "Invalid answer") except Exception as e: # When no answer is given, redirect to results instead return HttpResponseRedirect("/community/survey/%s-%s" % (surv.id, slugify(surv.question))) attrname = "tot%s" % ansnum # Do IP based locking... addr = get_client_ip(request) # Clean out any old junk curs = connection.cursor() curs.execute( "DELETE FROM survey_surveylock WHERE (\"time\" + '15 minutes') < now()" ) # Check if we are locked lock = SurveyLock.objects.filter(ipaddr=addr) if len(lock) > 0: return HttpSimpleResponse( request, "Rate limited", "Too many requests from your IP in the past 15 minutes") # Generate a new lock item, and store it lock = SurveyLock(ipaddr=addr) lock.save() answers = SurveyAnswer.objects.get_or_create(survey=surv)[0] setattr(answers, attrname, getattr(answers, attrname) + 1) answers.save() # Do explicit varnish purge, since it seems that the model doesn't # do it properly. Possibly because of the cute stuff we do with # getattr/setattr above. varnish_purge("/community/survey/%s/" % surveyid) return HttpResponseRedirect("/community/survey/%s/" % surveyid)
def signup_oauth(request): if 'oauth_email' not in request.session \ or 'oauth_firstname' not in request.session \ or 'oauth_lastname' not in request.session: return HttpSimpleResponse(request, "OAuth error", 'Invalid redirect received') # Is this email already on a different account as a secondary one? if SecondaryEmail.objects.filter( email=request.session['oauth_email'].lower()).exists(): return HttpSimpleResponse( request, "OAuth error", 'This email address is already attached to a different account') if request.method == 'POST': # Second stage, so create the account. But verify that the # nonce matches. data = request.POST.copy() data['email'] = request.session['oauth_email'].lower() data['first_name'] = request.session['oauth_firstname'] data['last_name'] = request.session['oauth_lastname'] form = SignupOauthForm(data=data) if form.is_valid(): log.info( "Creating user for {0} from {1} from oauth signin of email {2}" .format(form.cleaned_data['username'], get_client_ip(request), request.session['oauth_email'])) user = User.objects.create_user( form.cleaned_data['username'].lower(), request.session['oauth_email'].lower(), last_login=datetime.now()) user.first_name = request.session['oauth_firstname'] user.last_name = request.session['oauth_lastname'] user.password = OAUTH_PASSWORD_STORE user.save() # Clean up our session del request.session['oauth_email'] del request.session['oauth_firstname'] del request.session['oauth_lastname'] request.session.modified = True # We can immediately log the user in because their email # is confirmed. user.backend = settings.AUTHENTICATION_BACKENDS[0] django_login(request, user) # Redirect to the sessions page, or to the account page # if none was given. return HttpResponseRedirect( request.session.pop('login_next', '/account/')) elif 'do_abort' in request.GET: del request.session['oauth_email'] del request.session['oauth_firstname'] del request.session['oauth_lastname'] request.session.modified = True return HttpResponseRedirect(request.session.pop('login_next', '/')) else: # Generate possible new username suggested_username = request.session['oauth_email'].replace('@', '.')[:30] # Auto generation requires firstname and lastname to be specified f = request.session['oauth_firstname'].lower() l = request.session['oauth_lastname'].lower() if f and l: for u in itertools.chain([ "{0}{1}".format(f, l[0]), "{0}{1}".format(f[0], l), ], ("{0}{1}{2}".format(f, l[0], n) for n in range(100))): if not User.objects.filter(username=u[:30]).exists(): suggested_username = u[:30] break form = SignupOauthForm( initial={ 'username': suggested_username, 'email': request.session['oauth_email'].lower(), 'first_name': request.session['oauth_firstname'][:30], 'last_name': request.session['oauth_lastname'][:30], }) return render_pgweb( request, 'account', 'account/signup_oauth.html', { 'form': form, 'operation': 'New account', 'savebutton': 'Sign up for new account', 'recaptcha': True, })