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 _login_oauth(request, provider, authurl, tokenurl, scope, authdatafunc): from requests_oauthlib import OAuth2Session client_id = settings.OAUTH[provider]['clientid'] client_secret = settings.OAUTH[provider]['secret'] redir = '{0}/account/login/{1}/'.format(settings.SITE_ROOT, provider) oa = OAuth2Session(client_id, scope=scope, redirect_uri=redir) if request.GET.has_key('code'): log.info("Completing {0} oauth2 step from {1}".format( provider, get_client_ip(request))) # Receiving a login request from the provider, so validate data # and log the user in. if request.GET.get('state', '') != request.session.pop('oauth_state'): log.warning( "Invalid state received in {0} oauth2 step from {1}".format( provider, get_client_ip(request))) raise OAuthException("Invalid OAuth state received") token = oa.fetch_token(tokenurl, client_secret=client_secret, code=request.GET['code']) try: (email, firstname, lastname) = authdatafunc(oa) email = email.lower() except KeyError, e: log.warning("Oauth signing using {0} was missing data: {1}".format( provider, e)) return HttpResponse( 'OAuth login was missing critical data. To log in, you need to allow access to email, first name and last name!' ) try: user = User.objects.get(email=email) except User.DoesNotExist: log.info( "Oauth signin of {0} using {1} from {2}. User not found, offering signup." .format(email, provider, get_client_ip(request))) # Offer the user a chance to sign up. The full flow is # handled elsewhere, so store the details we got from # the oauth login in the session, and pass the user on. request.session['oauth_email'] = email request.session['oauth_firstname'] = firstname request.session['oauth_lastname'] = lastname return HttpResponseRedirect('/account/signup/oauth/') log.info("Oauth signin of {0} using {1} from {2}.".format( email, provider, get_client_ip(request))) user.backend = settings.AUTHENTICATION_BACKENDS[0] django_login(request, user) n = request.session.pop('login_next') if n: return HttpResponseRedirect(n) else: return HttpResponseRedirect('/account/')
def signup(request): if request.user.is_authenticated(): return HttpServerError(request, "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 _get_numeric_ip(request): try: ip = get_client_ip(request) p = ip.split('.') return int(p[0])*16777216 + int(p[1])*65536 + int(p[2])*256 + int(p[3]) except: return None
def system_information(request): return render_to_response('core/system_information.html', { 'server': uname()[1], 'behind_cache': is_behind_cache(request), 'cache_server': is_behind_cache(request) and request.META['REMOTE_ADDR'] or None, 'client_ip': get_client_ip(request), })
def system_information_ssl(request): return render_to_response('core/system_information.html', { 'server': os.uname()[1], 'behind_cache': False, 'cache_server': None, 'client_ip': get_client_ip(request), })
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 system_information(request): return render(request, 'core/system_information.html', { 'server': os.uname()[1], 'cache_server': request.META['REMOTE_ADDR'] or None, 'client_ip': get_client_ip(request), 'django_version': django.get_version(), })
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 HttpServerError(request, "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, form.cleaned_data['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 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 HttpServerError(request, "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, form.cleaned_data['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 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 HttpServerError("Invalid answer") except: # 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 HttpServerError("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() return HttpResponseRedirect("/community/survey/%s/" % surveyid)
def changepwd(request): if hasattr(request.user, 'password') and request.user.password == OAUTH_PASSWORD_STORE: return HttpServerError(request, "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.password_change(request, template_name='account/password_change.html', post_change_redirect='/account/changepwd/done/')
def reset_confirm(request, uidb64, token): log.info( "Confirming password reset for uidb {0}, token {1} from {2}".format( uidb64, token, get_client_ip(request))) return authviews.PasswordResetConfirmView.as_view( template_name='account/password_reset_confirm.html', success_url='/account/reset/complete/')(request, uidb64=uidb64, token=token)
def reset_confirm(request, uidb64, token): log.info( "Confirming password reset for uidb {0}, token {1} from {2}".format( uidb64, token, get_client_ip(request))) return authviews.password_reset_confirm( request, uidb64=uidb64, token=token, template_name='account/password_reset_confirm.html', post_reset_redirect='/account/reset/complete/')
def system_information(request): return render_to_response( "core/system_information.html", { "server": os.uname()[1], "behind_cache": is_behind_cache(request), "cache_server": is_behind_cache(request) and request.META["REMOTE_ADDR"] or None, "client_ip": get_client_ip(request), }, )
def changepwd(request): log.info("Initiating password change from {0}".format(get_client_ip(request))) return authviews.password_change(request, template_name='account/password_change.html', post_change_redirect='/account/changepwd/done/')
def reset_done(request): log.info("Password reset done from {0}".format(get_client_ip(request))) return authviews.PasswordResetDoneView.as_view( template_name='account/password_reset_done.html')(request)
request.session['oauth_email'] = email request.session['oauth_firstname'] = firstname or '' request.session['oauth_lastname'] = lastname or '' return HttpResponseRedirect('/account/signup/oauth/') log.info("Oauth signin of {0} using {1} from {2}.".format(email, provider, get_client_ip(request))) user.backend = settings.AUTHENTICATION_BACKENDS[0] django_login(request, user) n = request.session.pop('login_next') if n: return HttpResponseRedirect(n) else: return HttpResponseRedirect('/account/') else: log.info("Initiating {0} oauth2 step from {1}".format(provider, get_client_ip(request))) # First step is redirect to provider authorization_url, state = oa.authorization_url( authurl, prompt='consent', ) request.session['login_next'] = request.GET.get('next', '') request.session['oauth_state'] = state request.session.modified = True return HttpResponseRedirect(authorization_url) # # Google login # Registration: https://console.developers.google.com/apis/ #
def resetpwd(request): log.info("Initiating password set from {0}".format(get_client_ip(request))) return authviews.password_reset(request, template_name='account/password_reset.html', email_template_name='account/password_reset_email.txt', post_reset_redirect='/account/reset/done/')
def reset_complete(request): log.info("Password reset completed for user from {0}".format(get_client_ip(request))) return authviews.password_reset_complete(request, template_name='account/password_reset_complete.html')
def api_repo_updated(request): if not get_client_ip(request) in settings.SITE_UPDATE_HOSTS: return HttpServerError("Invalid client address") # Ignore methods and contents, just drop the trigger open(settings.SITE_UPDATE_TRIGGER_FILE, 'a').close() return HttpResponse("OK")
request.session['oauth_lastname'] = lastname return HttpResponseRedirect('/account/signup/oauth/') log.info("Oauth signin of {0} using {1} from {2}.".format( email, provider, get_client_ip(request))) user.backend = settings.AUTHENTICATION_BACKENDS[0] django_login(request, user) n = request.session.pop('login_next') if n: return HttpResponseRedirect(n) else: return HttpResponseRedirect('/account/') else: log.info("Initiating {0} oauth2 step from {1}".format( provider, get_client_ip(request))) # First step is redirect to provider authorization_url, state = oa.authorization_url( authurl, prompt='consent', ) request.session['login_next'] = request.GET.get('next', '') request.session['oauth_state'] = state request.session.modified = True return HttpResponseRedirect(authorization_url) # # Google login # Registration: https://console.developers.google.com/apis/ #
def change_done(request): log.info("Password change done from {0}".format(get_client_ip(request))) return authviews.password_change_done(request, template_name='account/password_change_done.html')
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 HttpServerError(request, 'Invalid redirect received') 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, })
def _login_oauth(request, provider, authurl, tokenurl, scope, authdatafunc): from requests_oauthlib import OAuth2Session client_id = settings.OAUTH[provider]['clientid'] client_secret = settings.OAUTH[provider]['secret'] redir = '{0}/account/login/{1}/'.format(settings.SITE_ROOT, provider) oa = OAuth2Session(client_id, scope=scope, redirect_uri=redir) if 'code' in request.GET: log.info("Completing {0} oauth2 step from {1}".format(provider, get_client_ip(request))) # Receiving a login request from the provider, so validate data # and log the user in. if request.GET.get('state', '') != request.session.pop('oauth_state'): log.warning("Invalid state received in {0} oauth2 step from {1}".format(provider, get_client_ip(request))) raise OAuthException("Invalid OAuth state received") token = oa.fetch_token(tokenurl, client_secret=client_secret, code=request.GET['code']) try: (email, firstname, lastname) = authdatafunc(oa) email = email.lower() except KeyError as e: log.warning("Oauth signing using {0} was missing data: {1}".format(provider, e)) return HttpResponse('OAuth login was missing critical data. To log in, you need to allow access to email, first name and last name!') try: user = User.objects.get(email=email) except User.DoesNotExist: log.info("Oauth signin of {0} using {1} from {2}. User not found, offering signup.".format(email, provider, get_client_ip(request))) # Offer the user a chance to sign up. The full flow is # handled elsewhere, so store the details we got from # the oauth login in the session, and pass the user on. request.session['oauth_email'] = email request.session['oauth_firstname'] = firstname or '' request.session['oauth_lastname'] = lastname or '' return HttpResponseRedirect('/account/signup/oauth/') log.info("Oauth signin of {0} using {1} from {2}.".format(email, provider, get_client_ip(request))) if UserProfile.objects.filter(user=user).exists(): if UserProfile.objects.get(user=user).block_oauth: log.warning("Account {0} ({1}) is blocked from OAuth login".format(user.username, email)) return HttpResponse("OAuth login not allowed to this account.") user.backend = settings.AUTHENTICATION_BACKENDS[0] django_login(request, user) n = request.session.pop('login_next') if n: return HttpResponseRedirect(n) else: return HttpResponseRedirect('/account/') else: log.info("Initiating {0} oauth2 step from {1}".format(provider, get_client_ip(request))) # First step is redirect to provider authorization_url, state = oa.authorization_url( authurl, prompt='consent', ) request.session['login_next'] = request.GET.get('next', '') request.session['oauth_state'] = state request.session.modified = True return HttpResponseRedirect(authorization_url)
def reset_confirm(request, uidb36, token): log.info("Confirming password reset for uidb {0}, token {1} from {2}".format(uidb36, token, get_client_ip(request))) return authviews.password_reset_confirm(request, uidb36=uidb36, token=token, template_name='account/password_reset_confirm.html', post_reset_redirect='/account/reset/complete/')