def password_reset_confirm(request, uidb64=None, token=None): """ Pulled from django contrib so that we can add user into the form so then we can show relevant messages about the user. """ assert uidb64 is not None and token is not None user = None try: uid_int = urlsafe_base64_decode(uidb64) user = UserProfile.objects.get(id=uid_int) except (ValueError, UserProfile.DoesNotExist, TypeError): pass if user is not None and default_token_generator.check_token(user, token): validlink = True if request.method == 'POST': form = forms.SetPasswordForm(user, request.POST) if form.is_valid(): form.save() log_cef('Password Changed', 5, request, username=user.username, signature='PASSWORDCHANGED', msg='User changed password') return redirect(reverse('django.contrib.auth.' 'views.password_reset_complete')) else: form = forms.SetPasswordForm(user) else: validlink = False form = None return render(request, 'users/pwreset_confirm.html', {'form': form, 'validlink': validlink})
def password_reset_confirm(request, uidb64=None, token=None): """ Pulled from django contrib so that we can add user into the form so then we can show relevant messages about the user. """ assert uidb64 is not None and token is not None user = None try: uid_int = urlsafe_base64_decode(uidb64) user = UserProfile.objects.get(id=uid_int) except (ValueError, UserProfile.DoesNotExist): pass if user is not None and default_token_generator.check_token(user, token): validlink = True if request.method == "POST": form = forms.SetPasswordForm(user, request.POST) if form.is_valid(): form.save() log_cef( "Password Changed", 5, request, username=user.username, signature="PASSWORDCHANGED", msg="User changed password", ) return redirect(reverse("django.contrib.auth." "views.password_reset_complete")) else: form = forms.SetPasswordForm(user) else: validlink = False form = None return render(request, "users/pwreset_confirm.html", {"form": form, "validlink": validlink})
def save(self, **kw): if not self.users_cache: log.info("Unknown email used for password reset: {email}".format( **self.cleaned_data)) return for user in self.users_cache: log.info(u'Password reset email sent for user (%s)' % user) if user.needs_tougher_password: log_cef('Password Reset', 5, self.request, username=user, signature='PASSWORDRESET', msg='Privileged user requested password reset') else: log_cef('Password Reset', 5, self.request, username=user, signature='PASSWORDRESET', msg='User requested password reset') try: # Django calls send_mail() directly and has no option to pass # in fail_silently, so we have to catch the SMTP error ourselves self.base_save(**kw) except SMTPException, e: log.error("Failed to send mail for (%s): %s" % (user, e))
def browserid_authenticate(request, assertion): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists on AMO, create one. Request is only needed for logging. :( """ backend = BrowserIDBackend() result = backend.verify(assertion, settings.SITE_URL) if not result: return (None, "BrowserID authentication failure.") email = result['email'] users = UserProfile.objects.filter(email=email) if len(users) == 1: users[0].user.backend = 'django_browserid.auth.BrowserIDBackend' return (users[0], None) username = autocreate_username(email.partition('@')[0]) if (settings.REGISTER_USER_LIMIT and UserProfile.objects.count() > settings.REGISTER_USER_LIMIT and not can_override_reg_limit(request)): _m = ('Sorry, no more registrations are allowed. ' '<a href="https://developer.mozilla.org/en-US/apps">' 'Learn more</a>') return (None, _m) profile = UserProfile.objects.create(username=username, email=email) profile.create_django_user() profile.user.backend = 'django_browserid.auth.BrowserIDBackend' if settings.APP_PREVIEW: profile.notes = '__market__' profile.user.save() profile.save() log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from BrowserID)') return (profile, None)
def browserid_authenticate(request, assertion): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists on AMO, create one. Request is only needed for logging. :( """ backend = BrowserIDBackend() result = backend.verify(assertion, settings.SITE_URL) if not result: return (None, "BrowserID authentication failure.") email = result['email'] users = UserProfile.objects.filter(email=email) if len(users) == 1: users[0].user.backend = 'django_browserid.auth.BrowserIDBackend' return (users[0], None) username = autocreate_username(email.partition('@')[0]) source = (amo.LOGIN_SOURCE_MMO_BROWSERID if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID) profile = UserProfile.objects.create(username=username, email=email, source=source, display_name=username) profile.create_django_user() profile.user.backend = 'django_browserid.auth.BrowserIDBackend' profile.user.save() profile.save() log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from BrowserID)') return (profile, None)
def register(request): if settings.APP_PREVIEW: messages.error(request, loc('Registrations must be through browserid.')) form = None elif (settings.REGISTER_USER_LIMIT and UserProfile.objects.count() > settings.REGISTER_USER_LIMIT and not can_override_reg_limit(request)): _m = loc('Sorry, no more registrations are allowed. ' '<a href="https://developer.mozilla.org/en-US/apps">' 'Learn more</a>') messages.error(request, _m, title_safe=True, message_safe=True) form = None elif request.user.is_authenticated(): messages.info(request, _('You are already logged in to an account.')) form = None elif request.method == 'POST': form = forms.UserRegisterForm(request.POST) if form.is_valid(): try: u = form.save(commit=False) u.set_password(form.cleaned_data['password']) u.generate_confirmationcode() u.save() u.create_django_user() log.info(u'Registered new account for user (%s)', u) log_cef('New Account', 5, request, username=u.username, signature='AUTHNOTICE', msg='User created a new account') u.email_confirmation_code() msg = _('Congratulations! Your user account was successfully ' 'created.') messages.success(request, msg) msg = _(u'An email has been sent to your address {0} to ' 'confirm your account. Before you can log in, you ' 'have to activate your account by clicking on the ' 'link provided in this email.').format(u.email) messages.info(request, _('Confirmation Email Sent'), msg) except IntegrityError, e: # I was unable to reproduce this, but I suspect it happens # when they POST twice quickly and the slaves don't have the # new info yet (total guess). Anyway, I'm assuming the # first one worked properly, so this is still a success # case to tne end user so we just log it... log.error('Failed to register new user (%s): %s' % (u, e)) return http.HttpResponseRedirect(reverse('users.login')) else: messages.error(request, _('There are errors in this form'), _('Please correct them and resubmit.'))
def save(self, **kw): for user in self.users_cache: log.info(u"Password reset email sent for user (%s)" % user) if user.needs_tougher_password: log_cef( "Password Reset", 5, self.request, username=user, signature="PASSWORDRESET", msg="Privileged user requested password reset", ) else: log_cef( "Password Reset", 5, self.request, username=user, signature="PASSWORDRESET", msg="User requested password reset", ) try: # Django calls send_mail() directly and has no option to pass # in fail_silently, so we have to catch the SMTP error ourselves super(PasswordResetForm, self).save(**kw) except SMTPException, e: log.error("Failed to send mail for (%s): %s" % (user, e))
def password_reset_confirm(request, uidb36=None, token=None): """ Pulled from django contrib so that we can add user into the form so then we can show relevant messages about the user. """ assert uidb36 is not None and token is not None user = None try: uid_int = base36_to_int(uidb36) user = UserProfile.objects.get(id=uid_int) except (ValueError, UserProfile.DoesNotExist): pass if user is not None and default_token_generator.check_token(user, token): validlink = True if request.method == 'POST': form = forms.SetPasswordForm(user, request.POST) if form.is_valid(): form.save() log_cef('Password Changed', 5, request, username=user.username, signature='PASSWORDCHANGED', msg='User changed password') return redirect(reverse('django.contrib.auth.' 'views.password_reset_complete')) else: form = forms.SetPasswordForm(user) else: validlink = False form = None return jingo.render(request, 'users/pwreset_confirm.html', {'form': form, 'validlink': validlink})
def browserid_authenticate(request, assertion): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists on AMO, create one. Request is only needed for logging. :( """ backend = BrowserIDBackend() result = backend.verify(assertion, settings.SITE_URL) if not result: return (None, None) email = result['email'] users = UserProfile.objects.filter(email=email) if len(users) == 1: users[0].user.backend = 'django_browserid.auth.BrowserIDBackend' return (users[0], None) username = autocreate_username(email.partition('@')[0]) if (settings.REGISTER_USER_LIMIT and UserProfile.objects.count() > settings.REGISTER_USER_LIMIT and not can_override_reg_limit(request)): _m = ('Sorry, no more registrations are allowed. ' '<a href="https://developer.mozilla.org/en-US/apps">' 'Learn more</a>') return (None, _m) profile = UserProfile.objects.create(username=username, email=email) profile.create_django_user() profile.user.backend = 'django_browserid.auth.BrowserIDBackend' profile.user.save() profile.save() log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from BrowserID)') return (profile, None)
def cspreport(request): """Accept CSP reports and log them.""" report = ("blocked-uri", "violated-directive", "original-policy") if not waffle.sample_is_active("csp-store-reports"): return HttpResponse() try: v = json.loads(request.body)["csp-report"] # If possible, alter the PATH_INFO to contain the request of the page # the error occurred on, spec: http://mzl.la/P82R5y meta = request.META.copy() meta["PATH_INFO"] = v.get("document-uri", meta["PATH_INFO"]) v = [(k, v[k]) for k in report if k in v] log_cef( "CSPViolation", 5, meta, username=request.user, signature="CSPREPORT", msg="A client reported a CSP violation", cs6=v, cs6Label="ContentPolicy", ) except (KeyError, ValueError), e: log.debug("Exception in CSP report: %s" % e, exc_info=True) return HttpResponseBadRequest()
def _fxa_authorize(fxa, client_secret, request, auth_response): token = fxa.fetch_token( fxa_oauth_api('token'), authorization_response=auth_response, client_secret=client_secret) res = fxa.post(fxa_oauth_api('verify'), data=json.dumps({'token': token['access_token']}), headers={'Content-Type': 'application/json'}) data = res.json() if 'user' in data: email = data['email'] username = data['user'] try: profile = UserProfile.objects.get(email=email) except UserProfile.DoesNotExist: source = amo.LOGIN_SOURCE_FXA profile = UserProfile.objects.create( username=username, email=email, source=source, display_name=email.partition('@')[0], is_verified=True) log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from FxA)') record_action('new-user', request) auth.login(request, profile) profile.log_login_attempt(True) auth.signals.user_logged_in.send( sender=profile.__class__, request=request, user=profile) return profile
def cspreport(request): """Accept CSP reports and log them.""" report = ("blocked-uri", "violated-directive", "original-policy") if not waffle.sample_is_active("csp-store-reports"): return HttpResponse() try: v = json.loads(request.raw_post_data)["csp-report"] # CEF module wants a dictionary of environ, we want request # to be the page with error on it, that's contained in the csp-report # so we need to modify the meta before we pass in to the logger meta = request.META.copy() method, url = v["request"].split(" ", 1) meta.update({"REQUEST_METHOD": method, "PATH_INFO": url}) v = [(k, v[k]) for k in report if k in v] log_cef( "CSP Violation", 5, meta, username=request.user, signature="CSPREPORT", msg="A client reported a CSP violation", cs7=v, cs7Label="ContentPolicy", ) except Exception, e: log.debug("Exception in CSP report: %s" % e, exc_info=True) return HttpResponseBadRequest()
def cspreport(request): """Accept CSP reports and log them.""" report = ('blocked-uri', 'violated-directive', 'original-policy') if not waffle.sample_is_active('csp-store-reports'): return HttpResponse() try: v = json.loads(request.body)['csp-report'] # If possible, alter the PATH_INFO to contain the request of the page # the error occurred on, spec: http://mzl.la/P82R5y meta = request.META.copy() meta['PATH_INFO'] = v.get('document-uri', meta['PATH_INFO']) v = [(k, v[k]) for k in report if k in v] log_cef('CSP Violation', 5, meta, username=request.user, signature='CSPREPORT', msg='A client reported a CSP violation', cs6=v, cs6Label='ContentPolicy') except (KeyError, ValueError), e: log.debug('Exception in CSP report: %s' % e, exc_info=True) return HttpResponseBadRequest()
def save(self, log_for_developer=True): u = super(UserEditForm, self).save(commit=False) data = self.cleaned_data photo = data['photo'] if photo: u.picture_type = 'image/png' tmp_destination = u.picture_path + '__unconverted' with storage.open(tmp_destination, 'wb') as fh: for chunk in photo.chunks(): fh.write(chunk) tasks.resize_photo.delay(tmp_destination, u.picture_path, set_modified_on=[u]) if data['password']: u.set_password(data['password']) log_cef('Password Changed', 5, self.request, username=u.username, signature='PASSWORDCHANGED', msg='User changed password') if log_for_developer: amo.log(amo.LOG.CHANGE_PASSWORD) log.info(u'User (%s) changed their password' % u) for (i, n) in email.NOTIFICATIONS_BY_ID.items(): enabled = n.mandatory or (str(i) in data['notifications']) UserNotification.update_or_create(user=u, notification_id=i, update={'enabled': enabled}) log.debug(u'User (%s) updated their profile' % u) u.save() return u
def cspreport(request): """Accept CSP reports and log them.""" report = ('blocked-uri', 'violated-directive', 'original-policy') if not waffle.sample_is_active('csp-store-reports'): return HttpResponse() try: v = json.loads(request.raw_post_data)['csp-report'] # CEF module wants a dictionary of environ, we want request # to be the page with error on it, that's contained in the csp-report # so we need to modify the meta before we pass in to the logger meta = request.META.copy() method, url = v['request'].split(' ', 1) meta.update({'REQUEST_METHOD': method, 'PATH_INFO': url}) v = [(k, v[k]) for k in report if k in v] log_cef('CSP Violation', 5, meta, username=request.user, signature='CSPREPORT', msg='A client reported a CSP violation', cs7=v, cs7Label='ContentPolicy') except Exception, e: log.debug('Exception in CSP report: %s' % e, exc_info=True) return HttpResponseBadRequest()
def save(self, **kw): # Three different loggers? :( amo.log(amo.LOG.CHANGE_PASSWORD, user=self.user) log.info(u'User (%s) changed password with reset form' % self.user) log_cef('Password Changed', 5, self.request, username=self.user.username, signature='PASSWORDCHANGED', msg='User changed password') super(SetPasswordForm, self).save(**kw)
def register(request): if request.user.is_authenticated(): messages.info(request, _('You are already logged in to an account.')) form = None elif request.method == 'POST': form = forms.UserRegisterForm(request.POST) mkt_user = UserProfile.objects.filter(email=form.data['email'], password='') if form.is_valid(): try: u = form.save(commit=False) u.set_password(form.cleaned_data['password']) u.generate_confirmationcode() u.lang = request.LANG u.save() log.info(u'Registered new account for user (%s)', u) log_cef('New Account', 5, request, username=u.username, signature='AUTHNOTICE', msg='User created a new account') u.email_confirmation_code() msg = _('Congratulations! Your user account was ' 'successfully created.') messages.success(request, msg) msg = _(u'An email has been sent to your address {0} to ' 'confirm your account. Before you can log in, you ' 'have to activate your account by clicking on the ' 'link provided in this email.').format(u.email) messages.info(request, _('Confirmation Email Sent'), msg) except IntegrityError, e: # I was unable to reproduce this, but I suspect it happens # when they POST twice quickly and the slaves don't have the # new info yet (total guess). Anyway, I'm assuming the # first one worked properly, so this is still a success # case to the end user so we just log it... log.error('Failed to register new user (%s): %s' % (u, e)) return http.HttpResponseRedirect(reverse('users.login')) elif mkt_user.exists(): f = PasswordResetForm() f.users_cache = [mkt_user[0]] f.save(use_https=request.is_secure(), email_template_name='users/email/pwreset.ltxt', request=request) return render(request, 'users/newpw_sent.html', {}) else: messages.error(request, _('There are errors in this form'), _('Please correct them and resubmit.'))
def _login(request, template=None, data=None, dont_redirect=False): data = data or {} data['webapp'] = True # In case we need it later. See below. get_copy = request.GET.copy() if 'to' in request.GET: request = _clean_next_url(request) if request.user.is_authenticated(): return http.HttpResponseRedirect( request.GET.get('to', settings.LOGIN_REDIRECT_URL)) user = None login_status = None r = auth_login(request, template_name=template, redirect_field_name='to', extra_context=data) if isinstance(r, http.HttpResponseRedirect): # Django's auth.views.login has security checks to prevent someone from # redirecting to another domain. Since we want to allow this in # certain cases, we have to make a new response object here to replace # the above. if 'domain' in request.GET: request.GET = get_copy request = _clean_next_url(request) r = http.HttpResponseRedirect(request.GET['to']) # Succsesful log in according to django. Now we do our checks. I do # the checks here instead of the form's clean() because I want to use # the messages framework and it's not available in the request there. if user.deleted: logout(request) log.warning(u'Attempt to log in with deleted account (%s)' % user) messages.error(request, _('Wrong email address or password!')) user.log_login_attempt(False) log_cef('Authentication Failure', 5, request, username=request.user, signature='AUTHFAIL', msg='Account is deactivated') return render(request, template, data) login_status = True if dont_redirect: # We're recalling the middleware to re-initialize amo_user ACLMiddleware().process_request(request) r = render(request, template, data) if login_status is not None: user.log_login_attempt(login_status) log_cef('Authentication Failure', 5, request, username=request.POST['username'], signature='AUTHFAIL', msg='The password was incorrect') return r
def browserid_authenticate(request, assertion, is_mobile=False, browserid_audience=get_audience): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists, create one. """ extra_params = {} url = settings.NATIVE_FXA_VERIFICATION_URL log.debug('Verifying Native FxA at %s, audience: %s, ' 'extra_params: %s' % (url, browserid_audience, extra_params)) v = BrowserIDBackend().get_verifier() v.verification_service_url = url result = v.verify(assertion, browserid_audience, url=url, **extra_params) if not result: return None, _('Native FxA authentication failure.') if 'unverified-email' in result._response: email = result._response['unverified-email'] verified = False elif (result._response.get('issuer') == settings.NATIVE_FXA_ISSUER and 'fxa-verifiedEmail' in result._response.get('idpClaims', {})): email = result._response['idpClaims']['fxa-verifiedEmail'] verified = True else: email = result.email verified = True try: profile = UserProfile.objects.filter(email=email)[0] except IndexError: profile = None if profile: if profile.is_verified and not verified: # An attempt to log in to a verified address with an unverified # assertion is a very bad thing. Don't let that happen. log.debug('Verified user %s attempted to log in with an ' 'unverified assertion!' % profile) return None, _('Please use the verified email for this account.') else: profile.is_verified = verified profile.save() return profile, None username = autocreate_username(email.partition('@')[0]) source = amo.LOGIN_SOURCE_MMO_BROWSERID profile = UserProfile.objects.create(username=username, email=email, source=source, display_name=username, is_verified=verified) log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from Persona)') record_action('new-user', request) return profile, None
def register(request): if waffle.switch_is_active('fxa-auth'): return login(request) if request.user.is_authenticated(): messages.info(request, _('You are already logged in to an account.')) form = None elif request.method == 'POST': form = forms.UserRegisterForm(request.POST) mkt_user = UserProfile.objects.filter(email=form.data['email'], password='') if form.is_valid(): try: u = form.save(commit=False) u.set_password(form.cleaned_data['password']) u.generate_confirmationcode() u.lang = request.LANG u.save() log.info(u'Registered new account for user (%s)', u) log_cef('New Account', 5, request, username=u.username, signature='AUTHNOTICE', msg='User created a new account') u.email_confirmation_code() msg = _('Congratulations! Your user account was ' 'successfully created.') messages.success(request, msg) msg = _(u'An email has been sent to your address {0} to ' 'confirm your account. Before you can log in, you ' 'have to activate your account by clicking on the ' 'link provided in this email.').format(u.email) messages.info(request, _('Confirmation Email Sent'), msg) except IntegrityError, e: # I was unable to reproduce this, but I suspect it happens # when they POST twice quickly and the slaves don't have the # new info yet (total guess). Anyway, I'm assuming the # first one worked properly, so this is still a success # case to the end user so we just log it... log.error('Failed to register new user (%s): %s' % (u, e)) return http.HttpResponseRedirect(reverse('users.login')) elif mkt_user.exists(): f = PasswordResetForm() f.users_cache = [mkt_user[0]] f.save(use_https=request.is_secure(), email_template_name='users/email/pwreset.ltxt', request=request) return render(request, 'users/newpw_sent.html', {}) else: messages.error(request, _('There are errors in this form'), _('Please correct them and resubmit.'))
def paypal_log_cef(request, addon, uuid, msg, caps, longer): log_cef('Paypal %s' % msg, 5, request, username=request.amo_user, signature='PAYPAL%s' % caps, msg=longer, cs2=addon.name, cs2Label='PaypalTransaction', cs4=uuid, cs4Label='TxID')
def paypal_log_cef(request, addon, uuid, msg, caps, longer): log_cef( "Paypal %s" % msg, 5, request, username=request.amo_user, signature="PAYPAL%s" % caps, msg=longer, cs2=addon.name, cs2Label="PaypalTransaction", cs4=uuid, cs4Label="TxID", )
def _fxa_authorize(fxa, client_secret, request, auth_response, userid): token = fxa.fetch_token(fxa_oauth_api('token'), authorization_response=auth_response, client_secret=client_secret) res = fxa.post(fxa_oauth_api('verify'), data=json.dumps({'token': token['access_token']}), headers={'Content-Type': 'application/json'}) data = res.json() if 'user' in data: email = data['email'] fxa_uid = data['user'] def find_user(**kwargs): try: return UserProfile.objects.get(**kwargs) except UserProfile.DoesNotExist: return None profile = (find_user(pk=userid) or find_user(username=fxa_uid) or find_user(email=email)) if profile: profile.update(username=fxa_uid, email=email) else: profile = UserProfile.objects.create( username=fxa_uid, email=email, source=amo.LOGIN_SOURCE_FXA, display_name=email.partition('@')[0], is_verified=True) log_cef('New Account', 5, request, username=fxa_uid, signature='AUTHNOTICE', msg='User created a new account (from FxA)') record_action('new-user', request) if profile.source != amo.LOGIN_SOURCE_FXA: profile.update(source=amo.LOGIN_SOURCE_FXA) auth.login(request, profile) profile.log_login_attempt(True) auth.signals.user_logged_in.send(sender=profile.__class__, request=request, user=profile) return profile
def explode(self): error = self.cleaned_data.get('error') if error == 'zerodivisionerror': 1 / 0 elif error == 'iorequesterror': class IOError(Exception): pass raise IOError('request data read error') elif error == 'heka_cef': environ = {'REMOTE_ADDR': '127.0.0.1', 'HTTP_HOST': '127.0.0.1', 'PATH_INFO': '/', 'REQUEST_METHOD': 'GET', 'HTTP_USER_AGENT': 'MySuperBrowser'} config = {'cef.version': '0', 'cef.vendor': 'Mozilla', 'cef.device_version': '3', 'cef.product': 'zamboni', 'cef': True} settings.HEKA.cef( 'xx\nx|xx\rx', 5, environ, config, username='******', ext1='ok=ok', ext2='ok\\ok', logger_info='settings.HEKA') elif error == 'heka_statsd': settings.HEKA.incr(name=LOGGER_NAME) elif error == 'heka_json': settings.HEKA.heka( type="heka_json", fields={'foo': 'bar', 'secret': 42, 'logger_type': 'settings.HEKA'}) elif error == 'heka_sentry': # These are local variables only used # by Sentry's frame hacking magic. # They won't be referenced which may trigger flake8 # errors. heka_conf = settings.HEKA_CONF # NOQA active_heka_conf = settings.HEKA._config # NOQA try: 1 / 0 except: settings.HEKA.raven('heka_sentry error triggered') elif error == 'amo_cef': from amo.utils import log_cef env = {'REMOTE_ADDR': '127.0.0.1', 'HTTP_HOST': '127.0.0.1', 'PATH_INFO': '/', 'REQUEST_METHOD': 'GET', 'HTTP_USER_AGENT': 'MySuperBrowser'} log_cef(settings.STATSD_PREFIX, 6, env)
def _fxa_authorize(fxa, client_secret, request, auth_response, userid): token = fxa.fetch_token( fxa_oauth_api('token'), authorization_response=auth_response, client_secret=client_secret) res = fxa.post(fxa_oauth_api('verify'), data=json.dumps({'token': token['access_token']}), headers={'Content-Type': 'application/json'}) data = res.json() if 'user' in data: email = data['email'] fxa_uid = data['user'] def find_user(**kwargs): try: return UserProfile.objects.get(**kwargs) except UserProfile.DoesNotExist: return None profile = (find_user(pk=userid) or find_user(username=fxa_uid) or find_user(email=email)) if profile: profile.update(username=fxa_uid, email=email) else: profile = UserProfile.objects.create( username=fxa_uid, email=email, source=amo.LOGIN_SOURCE_FXA, display_name=email.partition('@')[0], is_verified=True) log_cef('New Account', 5, request, username=fxa_uid, signature='AUTHNOTICE', msg='User created a new account (from FxA)') record_action('new-user', request) if profile.source != amo.LOGIN_SOURCE_FXA: log.info('Set account to FxA for {0}'.format(email)) statsd.incr('z.mkt.user.fxa') profile.update(source=amo.LOGIN_SOURCE_FXA) auth.login(request, profile) profile.log_login_attempt(True) auth.signals.user_logged_in.send(sender=profile.__class__, request=request, user=profile) return profile
def browserid_authenticate(request, assertion): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists on AMO, create one. Request is only needed for logging. :( """ backend = BrowserIDBackend() result = backend.verify(assertion, settings.SITE_URL) if not result: return (None, "BrowserID authentication failure.") email = result["email"] users = UserProfile.objects.filter(email=email) if len(users) == 1: users[0].user.backend = "django_browserid.auth.BrowserIDBackend" return (users[0], None) username = autocreate_username(email.partition("@")[0]) if ( settings.REGISTER_USER_LIMIT and UserProfile.objects.count() > settings.REGISTER_USER_LIMIT and not can_override_reg_limit(request) ): _m = ( "Sorry, no more registrations are allowed. " '<a href="https://developer.mozilla.org/en-US/apps">' "Learn more</a>" ) return (None, _m) profile = UserProfile.objects.create( username=username, email=email, source=amo.LOGIN_SOURCE_BROWSERID, display_name=username ) profile.create_django_user() profile.user.backend = "django_browserid.auth.BrowserIDBackend" if settings.APP_PREVIEW: profile.notes = "__market__" profile.user.save() profile.save() log_cef( "New Account", 5, request, username=username, signature="AUTHNOTICE", msg="User created a new account (from BrowserID)", ) return (profile, None)
def save(self, *args, **kw): profile = super(AdminUserEditForm, self).save(log_for_developer=False) if self.cleaned_data['anonymize']: amo.log(amo.LOG.ADMIN_USER_ANONYMIZED, self.instance, self.cleaned_data['admin_log']) profile.anonymize() # This also logs else: amo.log(amo.LOG.ADMIN_USER_EDITED, self.instance, self.cleaned_data['admin_log'], details=self.changes()) log.info('Admin edit user: %s changed fields: %s' % (self.instance, self.changed_fields())) if 'password' in self.changes(): log_cef('Password Changed', 5, self.request, username=self.instance.username, signature='PASSWORDRESET', msg='Admin requested password reset', cs1=self.request.amo_user.username, cs1Label='AdminName') return profile
def save(self, *args, **kw): profile = super(AdminUserEditForm, self).save(log_for_developer=False) if self.cleaned_data["anonymize"]: amo.log(amo.LOG.ADMIN_USER_ANONYMIZED, self.instance, self.cleaned_data["admin_log"]) profile.anonymize() # This also logs else: amo.log(amo.LOG.ADMIN_USER_EDITED, self.instance, self.cleaned_data["admin_log"], details=self.changes()) log.info("Admin edit user: %s changed fields: %s" % (self.instance, self.changed_fields())) if "password" in self.changes(): log_cef( "Password Changed", 5, self.request, username=self.instance.username, signature="PASSWORDRESET", msg="Admin requested password reset", cs1=self.request.amo_user.username, cs1Label="AdminName", ) return profile
def save(self, **kw): if not self.users_cache: log.info("Unknown email used for password reset: {email}".format(**self.cleaned_data)) return for user in self.users_cache: log.info(u'Password reset email sent for user (%s)' % user) if user.needs_tougher_password: log_cef('Password Reset', 5, self.request, username=user, signature='PASSWORDRESET', msg='Privileged user requested password reset') else: log_cef('Password Reset', 5, self.request, username=user, signature='PASSWORDRESET', msg='User requested password reset') try: # Django calls send_mail() directly and has no option to pass # in fail_silently, so we have to catch the SMTP error ourselves self.base_save(**kw) except SMTPException, e: log.error("Failed to send mail for (%s): %s" % (user, e))
def create_action(self, request, serializer): client_id = request.POST.get('client_id', settings.FXA_CLIENT_ID) secret = settings.FXA_SECRETS[client_id] session = OAuth2Session(client_id, scope=u'profile', state=serializer.data['state']) try: # Maybe this was a preverified login to migrate a user. userid = Signer().unsign(serializer.data['state']) except BadSignature: userid = None auth_response = serializer.data['auth_response'] fxa_authorization = fxa_authorize(session, secret, auth_response) if 'user' in fxa_authorization: email = fxa_authorization['email'] fxa_uid = fxa_authorization['user'] profile, created = find_or_create_user(email, fxa_uid, userid) if created: log_cef('New Account', 5, request, username=fxa_uid, signature='AUTHNOTICE', msg='User created a new account (from FxA)') record_action('new-user', request) auth.login(request, profile) profile.log_login_attempt(True) auth.signals.user_logged_in.send(sender=profile.__class__, request=request, user=profile) else: raise AuthenticationFailed('No profile.') request.user = profile request.groups = profile.groups.all() # Remember whether the user has logged in to highlight the register or # sign in nav button. 31536000 == one year. request.set_cookie('has_logged_in', '1', max_age=5 * 31536000) # We want to return completely custom data, not the serializer's. data = { 'error': None, 'token': commonplace_token(request.user.email), 'settings': { 'display_name': request.user.display_name, 'email': request.user.email, 'enable_recommendations': request.user.enable_recommendations, 'source': 'firefox-accounts', } } # Serializers give up if they aren't passed an instance, so we # do that here despite PermissionsSerializer not needing one # really. permissions = PermissionsSerializer(context={'request': request}, instance=True) data.update(permissions.data) # Add ids of installed/purchased/developed apps. data['apps'] = user_relevant_apps(profile) return data
def _login(request, template=None, data=None, dont_redirect=False): data = data or {} # In case we need it later. See below. get_copy = request.GET.copy() if 'to' in request.GET: request = _clean_next_url(request) if request.user.is_authenticated(): return http.HttpResponseRedirect( request.GET.get('to', settings.LOGIN_REDIRECT_URL)) limited = getattr(request, 'limited', 'recaptcha_shown' in request.POST) user = None login_status = None if 'username' in request.POST: try: # We are doing all this before we try and validate the form. user = UserProfile.objects.get(email=request.POST['username']) limited = ( (user.failed_login_attempts >= settings.LOGIN_RATELIMIT_USER) or limited) login_status = False except UserProfile.DoesNotExist: log_cef('Authentication Failure', 5, request, username=request.POST['username'], signature='AUTHFAIL', msg='The username was invalid') pass partial_form = partial(forms.AuthenticationForm, use_recaptcha=limited) r = auth.views.login(request, template_name=template, redirect_field_name='to', authentication_form=partial_form, extra_context=data) if isinstance(r, http.HttpResponseRedirect): # Django's auth.views.login has security checks to prevent someone from # redirecting to another domain. Since we want to allow this in # certain cases, we have to make a new response object here to replace # the above. if 'domain' in request.GET: request.GET = get_copy request = _clean_next_url(request) r = http.HttpResponseRedirect(request.GET['to']) # Succsesful log in according to django. Now we do our checks. I do # the checks here instead of the form's clean() because I want to use # the messages framework and it's not available in the request there. if user.deleted: logout(request) log.warning(u'Attempt to log in with deleted account (%s)' % user) messages.error(request, _('Wrong email address or password!')) data.update({'form': partial_form()}) user.log_login_attempt(False) log_cef('Authentication Failure', 5, request, username=request.user, signature='AUTHFAIL', msg='Account is deactivated') return render(request, template, data) if user.confirmationcode: logout(request) log.info(u'Attempt to log in with unconfirmed account (%s)' % user) msg1 = _(u'A link to activate your user account was sent by email ' u'to your address {0}. You have to click it before you ' u'can log in.').format(user.email) url = "%s%s" % (settings.SITE_URL, reverse('users.confirm.resend', args=[user.id])) msg2 = _('If you did not receive the confirmation email, make ' 'sure your email service did not mark it as "junk ' 'mail" or "spam". If you need to, you can have us ' '<a href="%s">resend the confirmation message</a> ' 'to your email address mentioned above.') % url messages.error(request, _('Activation Email Sent'), msg1) messages.info(request, _('Having Trouble?'), msg2, title_safe=True, message_safe=True) data.update({'form': partial_form()}) user.log_login_attempt(False) return render(request, template, data) rememberme = request.POST.get('rememberme', None) if rememberme: request.session.set_expiry(settings.SESSION_COOKIE_AGE) log.debug( u'User (%s) logged in successfully with "remember me" set' % user) login_status = True if dont_redirect: # We're recalling the middleware to re-initialize amo_user ACLMiddleware().process_request(request) r = render(request, template, data) if login_status is not None: user.log_login_attempt(login_status) log_cef('Authentication Failure', 5, request, username=request.POST['username'], signature='AUTHFAIL', msg='The password was incorrect') return r
def browserid_authenticate(request, assertion, is_mobile=False, browserid_audience=get_audience): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists, create one. """ url = settings.BROWSERID_VERIFICATION_URL # We must always force the Firefox OS identity provider. This is because # we are sometimes allowing unverified assertions and you can't mix that # feature with bridged IdPs. See bug 910938. extra_params = {} if settings.UNVERIFIED_ISSUER: extra_params['experimental_forceIssuer'] = settings.UNVERIFIED_ISSUER if is_mobile: # When persona is running in a mobile OS then we can allow unverified # assertions. url = settings.NATIVE_BROWSERID_VERIFICATION_URL extra_params['experimental_allowUnverified'] = 'true' log.debug('Verifying Persona at %s, audience: %s, ' 'extra_params: %s' % (url, browserid_audience, extra_params)) result = verify(assertion, browserid_audience, url=url, extra_params=extra_params) if not result: return None, _('Persona authentication failure.') if 'unverified-email' in result: email = result['unverified-email'] verified = False else: email = result['email'] verified = True try: profile = UserProfile.objects.filter(email=email)[0] except IndexError: profile = None if profile: if profile.is_verified and not verified: # An attempt to log in to a verified address with an unverified # assertion is a very bad thing. Don't let that happen. log.debug('Verified user %s attempted to log in with an ' 'unverified assertion!' % profile) return None, _('Please use the verified email for this account.') else: profile.is_verified = verified profile.save() return profile, None username = autocreate_username(email.partition('@')[0]) source = amo.LOGIN_SOURCE_AMO_BROWSERID profile = UserProfile.objects.create(username=username, email=email, source=source, display_name=username, is_verified=verified) log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from Persona)') return profile, None
def browserid_authenticate(request, assertion, is_native=False): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists, create one. """ url = settings.BROWSERID_VERIFICATION_URL extra_params = None if is_native: # When persona is running native on B2G then we need to # verify assertions with the right service. # We also need to force the appropriate issuer # for potentially unverified emails. url = settings.NATIVE_BROWSERID_VERIFICATION_URL extra_params = {'issuer': settings.UNVERIFIED_ISSUER, 'allowUnverified': 'true'} audience = get_audience(request) log.debug('Verifying Persona at %s, audience: %s, ' 'extra_params: %s' % (url, audience, extra_params)) result = verify(assertion, audience, url=url, extra_params=extra_params) if not result: return None, _('Persona authentication failure.') if 'unverified-email' in result: email = result['unverified-email'] verified = False else: email = result['email'] verified = True try: profile = UserProfile.objects.filter(email=email)[0] except IndexError: profile = None if profile: if profile.is_verified and not verified: # An attempt to log in to a verified address with an unverified # assertion is a very bad thing. However, the same email address # can legitimately be used on the site on desktop and be verified # whilst be used on b2g and be unverified. We are forcing the # issuer, so this shouldn't be an issue. # # Blame kumar. Or cvan. Or deal with it. log.debug('Verified user %s attempted to log in with an ' 'unverified assertion!' % profile) else: profile.is_verified = verified profile.save() backend = 'django_browserid.auth.BrowserIDBackend' if getattr(profile.user, 'backend', None) != backend: profile.user.backend = backend profile.user.save() return profile, None username = autocreate_username(email.partition('@')[0]) source = (amo.LOGIN_SOURCE_MMO_BROWSERID if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID) profile = UserProfile.objects.create(username=username, email=email, source=source, display_name=username, is_verified=verified) profile.create_django_user( backend='django_browserid.auth.BrowserIDBackend') log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from Persona)') return profile, None
def browserid_authenticate(request, assertion, is_mobile=False, browserid_audience=get_audience): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists, create one. """ url = settings.BROWSERID_VERIFICATION_URL # We must always force the Firefox OS identity provider. This is because # we are sometimes allowing unverified assertions and you can't mix that # feature with bridged IdPs. See bug 910938. extra_params = {} if settings.UNVERIFIED_ISSUER: extra_params["experimental_forceIssuer"] = settings.UNVERIFIED_ISSUER if is_mobile: # When persona is running in a mobile OS then we can allow unverified # assertions. url = settings.NATIVE_BROWSERID_VERIFICATION_URL extra_params["experimental_allowUnverified"] = "true" log.debug("Verifying Persona at %s, audience: %s, " "extra_params: %s" % (url, browserid_audience, extra_params)) result = verify(assertion, browserid_audience, url=url, extra_params=extra_params) if not result: return None, _("Persona authentication failure.") if "unverified-email" in result: email = result["unverified-email"] verified = False else: email = result["email"] verified = True try: profile = UserProfile.objects.filter(email=email)[0] except IndexError: profile = None if profile: # Added due to bug 905984. It's possible to have a UserProfile # that has no corresponding User object. if profile.user is None: profile.create_django_user(backend="django_browserid.auth.BrowserIDBackend") if profile.is_verified and not verified: # An attempt to log in to a verified address with an unverified # assertion is a very bad thing. Don't let that happen. log.debug("Verified user %s attempted to log in with an " "unverified assertion!" % profile) return None, _("Please use the verified email for this account.") else: profile.is_verified = verified profile.save() backend = "django_browserid.auth.BrowserIDBackend" if getattr(profile.user, "backend", None) != backend: profile.user.backend = backend profile.user.save() return profile, None username = autocreate_username(email.partition("@")[0]) source = amo.LOGIN_SOURCE_MMO_BROWSERID if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID profile = UserProfile.objects.create( username=username, email=email, source=source, display_name=username, is_verified=verified ) profile.create_django_user(backend="django_browserid.auth.BrowserIDBackend") log_cef( "New Account", 5, request, username=username, signature="AUTHNOTICE", msg="User created a new account (from Persona)", ) if settings.MARKETPLACE: record_action("new-user", request) return profile, None
def browserid_authenticate(request, assertion, is_mobile=False, browserid_audience=get_audience): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists, create one. """ url = settings.BROWSERID_VERIFICATION_URL # We must always force the Firefox OS identity provider. This is because # we are sometimes allowing unverified assertions and you can't mix that # feature with bridged IdPs. See bug 910938. extra_params = {} if settings.UNVERIFIED_ISSUER: extra_params['experimental_forceIssuer'] = settings.UNVERIFIED_ISSUER if is_mobile: # When persona is running in a mobile OS then we can allow unverified # assertions. url = settings.NATIVE_BROWSERID_VERIFICATION_URL extra_params['experimental_allowUnverified'] = 'true' log.debug('Verifying Persona at %s, audience: %s, ' 'extra_params: %s' % (url, browserid_audience, extra_params)) result = verify(assertion, browserid_audience, url=url, extra_params=extra_params) if not result: return None, _('Persona authentication failure.') if 'unverified-email' in result: email = result['unverified-email'] verified = False else: email = result['email'] verified = True try: profile = UserProfile.objects.filter(email=email)[0] except IndexError: profile = None if profile: # Added due to bug 905984. It's possible to have a UserProfile # that has no corresponding User object. if profile.user is None: profile.create_django_user( backend='django_browserid.auth.BrowserIDBackend') if profile.is_verified and not verified: # An attempt to log in to a verified address with an unverified # assertion is a very bad thing. However, the same email address # can legitimately be used on the site on desktop and be verified # whilst be used on b2g and be unverified. We are forcing the # issuer, so this shouldn't be an issue. # # Blame kumar. Or cvan. Or deal with it. log.debug('Verified user %s attempted to log in with an ' 'unverified assertion!' % profile) else: profile.is_verified = verified profile.save() backend = 'django_browserid.auth.BrowserIDBackend' if getattr(profile.user, 'backend', None) != backend: profile.user.backend = backend profile.user.save() return profile, None username = autocreate_username(email.partition('@')[0]) source = (amo.LOGIN_SOURCE_MMO_BROWSERID if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID) profile = UserProfile.objects.create(username=username, email=email, source=source, display_name=username, is_verified=verified) profile.create_django_user( backend='django_browserid.auth.BrowserIDBackend') log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from Persona)') record_action('new-user', request) return profile, None
def register(request): if settings.APP_PREVIEW and waffle.switch_is_active("browserid-login"): messages.error(request, loc("Registrations must be through browserid.")) form = None raise http.Http404() elif request.user.is_authenticated(): messages.info(request, _("You are already logged in to an account.")) form = None elif request.method == "POST": form = forms.UserRegisterForm(request.POST) mkt_user = UserProfile.objects.filter(email=form.data["email"], password="") if form.is_valid(): try: u = form.save(commit=False) u.set_password(form.cleaned_data["password"]) u.generate_confirmationcode() u.save() u.create_django_user() log.info(u"Registered new account for user (%s)", u) log_cef( "New Account", 5, request, username=u.username, signature="AUTHNOTICE", msg="User created a new account", ) u.email_confirmation_code() msg = _("Congratulations! Your user account was " "successfully created.") messages.success(request, msg) msg = _( u"An email has been sent to your address {0} to " "confirm your account. Before you can log in, you " "have to activate your account by clicking on the " "link provided in this email." ).format(u.email) messages.info(request, _("Confirmation Email Sent"), msg) except IntegrityError, e: # I was unable to reproduce this, but I suspect it happens # when they POST twice quickly and the slaves don't have the # new info yet (total guess). Anyway, I'm assuming the # first one worked properly, so this is still a success # case to the end user so we just log it... log.error("Failed to register new user (%s): %s" % (u, e)) return http.HttpResponseRedirect(reverse("users.login")) elif mkt_user.exists(): # Handle BrowserID if mkt_user.count() == 1 and mkt_user[0].source in amo.LOGIN_SOURCE_BROWSERIDS: messages.info(request, _("You already have an account.")) form = None else: f = PasswordResetForm() f.users_cache = [mkt_user[0]] f.save(use_https=request.is_secure(), email_template_name="users/email/pwreset.ltxt", request=request) return jingo.render(request, "users/newpw_sent.html", {}) else: messages.error(request, _("There are errors in this form"), _("Please correct them and resubmit."))
def browserid_authenticate(request, assertion, is_mobile=False, browserid_audience=get_audience): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists, create one. """ extra_params = {} if waffle.switch_is_active('firefox-accounts'): url = settings.NATIVE_FXA_VERIFICATION_URL else: url = settings.BROWSERID_VERIFICATION_URL # We must always force the Firefox OS identity provider. This is # because we are sometimes allowing unverified assertions and you # can't mix that feature with bridged IdPs. See bug 910938. if settings.UNVERIFIED_ISSUER: extra_params['experimental_forceIssuer'] = settings.UNVERIFIED_ISSUER if is_mobile: # When persona is running in a mobile OS then we can allow # unverified assertions. url = settings.NATIVE_BROWSERID_VERIFICATION_URL extra_params['experimental_allowUnverified'] = 'true' log.debug('Verifying Persona at %s, audience: %s, ' 'extra_params: %s' % (url, browserid_audience, extra_params)) v = BrowserIDBackend().get_verifier() v.verification_service_url = url result = v.verify(assertion, browserid_audience, url=url, **extra_params) if not result: return None, _('Persona authentication failure.') if 'unverified-email' in result._response: email = result._response['unverified-email'] verified = False elif (result._response.get('issuer') == settings.NATIVE_FXA_ISSUER and 'fxa-verifiedEmail' in result._response.get('idpClaims', {})): email = result._response['idpClaims']['fxa-verifiedEmail'] verified = True else: email = result.email verified = True try: profile = UserProfile.objects.filter(email=email)[0] except IndexError: profile = None if profile: if profile.is_verified and not verified: # An attempt to log in to a verified address with an unverified # assertion is a very bad thing. Don't let that happen. log.debug('Verified user %s attempted to log in with an ' 'unverified assertion!' % profile) return None, _('Please use the verified email for this account.') else: profile.is_verified = verified profile.save() return profile, None username = autocreate_username(email.partition('@')[0]) source = amo.LOGIN_SOURCE_MMO_BROWSERID profile = UserProfile.objects.create(username=username, email=email, source=source, display_name=username, is_verified=verified) log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from Persona)') record_action('new-user', request) return profile, None
def browserid_authenticate(request, assertion, is_native=False, browserid_audience=get_audience): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists, create one. """ url = settings.BROWSERID_VERIFICATION_URL # We must always force the Firefox OS identity provider. This is because # we are sometimes allowing unverified assertions and you can't mix that # feature with bridged IdPs. See bug 910938. extra_params = {} if settings.UNVERIFIED_ISSUER: extra_params['experimental_forceIssuer'] = settings.UNVERIFIED_ISSUER if is_native: # When persona is running native on B2G then we can allow unverified # assertions. url = settings.NATIVE_BROWSERID_VERIFICATION_URL extra_params['experimental_allowUnverified'] = 'true' log.debug('Verifying Persona at %s, audience: %s, ' 'extra_params: %s' % (url, browserid_audience, extra_params)) result = verify(assertion, browserid_audience, url=url, extra_params=extra_params) if not result: return None, _('Persona authentication failure.') if 'unverified-email' in result: email = result['unverified-email'] verified = False else: email = result['email'] verified = True try: profile = UserProfile.objects.filter(email=email)[0] except IndexError: profile = None if profile: # Added due to bug 905984. It's possible to have a UserProfile # that has no corresponding User object. if profile.user is None: profile.create_django_user( backend='django_browserid.auth.BrowserIDBackend') if profile.is_verified and not verified: # An attempt to log in to a verified address with an unverified # assertion is a very bad thing. However, the same email address # can legitimately be used on the site on desktop and be verified # whilst be used on b2g and be unverified. We are forcing the # issuer, so this shouldn't be an issue. # # Blame kumar. Or cvan. Or deal with it. log.debug('Verified user %s attempted to log in with an ' 'unverified assertion!' % profile) else: profile.is_verified = verified profile.save() backend = 'django_browserid.auth.BrowserIDBackend' if getattr(profile.user, 'backend', None) != backend: profile.user.backend = backend profile.user.save() return profile, None username = autocreate_username(email.partition('@')[0]) source = (amo.LOGIN_SOURCE_MMO_BROWSERID if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID) profile = UserProfile.objects.create(username=username, email=email, source=source, display_name=username, is_verified=verified) profile.create_django_user( backend='django_browserid.auth.BrowserIDBackend') log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from Persona)') record_action('new-user', request) return profile, None
user_profile = UserProfile.objects.filter(email=buyer_email) if user_profile.exists(): user_profile = user_profile.get() else: buyer_username = autocreate_username(buyer_email.partition('@')[0]) source = amo.LOGIN_SOURCE_WEBPAY user_profile = UserProfile.objects.create(display_name=buyer_username, email=buyer_email, is_verified=True, source=source, username=buyer_username) log_cef('New Account', 5, request, username=buyer_username, signature='AUTHNOTICE', msg='A new account was created from Webpay (using FxA)') record_action('new-user', request) log.info('webpay postback: fulfilling purchase for contrib %s with ' 'transaction %s' % (contrib, trans_id)) app_pay_cef.log(request, 'Purchase complete', 'purchase_complete', 'Purchase complete for: %s' % (contrib.addon.pk), severity=3) contrib.update(transaction_id=trans_id, type=amo.CONTRIB_PURCHASE, user=user_profile,
def _login(request, template=None, data=None, dont_redirect=False): data = data or {} data['webapp'] = settings.APP_PREVIEW # In case we need it later. See below. get_copy = request.GET.copy() if 'to' in request.GET: request = _clean_next_url(request) if request.user.is_authenticated(): return http.HttpResponseRedirect( request.GET.get('to', settings.LOGIN_REDIRECT_URL)) limited = getattr(request, 'limited', 'recaptcha_shown' in request.POST) user = None login_status = None if 'username' in request.POST: try: # We are doing all this before we try and validate the form. user = UserProfile.objects.get(email=request.POST['username']) limited = ((user.failed_login_attempts >= settings.LOGIN_RATELIMIT_USER) or limited) login_status = False except UserProfile.DoesNotExist: log_cef('Authentication Failure', 5, request, username=request.POST['username'], signature='AUTHFAIL', msg='The username was invalid') pass partial_form = partial(forms.AuthenticationForm, use_recaptcha=limited) r = auth.views.login(request, template_name=template, redirect_field_name='to', authentication_form=partial_form, extra_context=data) if isinstance(r, http.HttpResponseRedirect): # Django's auth.views.login has security checks to prevent someone from # redirecting to another domain. Since we want to allow this in # certain cases, we have to make a new response object here to replace # the above. if 'domain' in request.GET: request.GET = get_copy request = _clean_next_url(request) r = http.HttpResponseRedirect(request.GET['to']) # Succsesful log in according to django. Now we do our checks. I do # the checks here instead of the form's clean() because I want to use # the messages framework and it's not available in the request there. user = request.user.get_profile() if user.deleted: logout(request) log.warning(u'Attempt to log in with deleted account (%s)' % user) messages.error(request, _('Wrong email address or password!')) data.update({'form': partial_form()}) user.log_login_attempt(False) log_cef('Authentication Failure', 5, request, username=request.user, signature='AUTHFAIL', msg='Account is deactivated') return jingo.render(request, template, data) if user.confirmationcode: logout(request) log.info(u'Attempt to log in with unconfirmed account (%s)' % user) msg1 = _(u'A link to activate your user account was sent by email ' 'to your address {0}. You have to click it before you ' 'can log in.').format(user.email) url = "%s%s" % (settings.SITE_URL, reverse('users.confirm.resend', args=[user.id])) msg2 = _('If you did not receive the confirmation email, make ' 'sure your email service did not mark it as "junk ' 'mail" or "spam". If you need to, you can have us ' '<a href="%s">resend the confirmation message</a> ' 'to your email address mentioned above.') % url messages.error(request, _('Activation Email Sent'), msg1) messages.info(request, _('Having Trouble?'), msg2, title_safe=True, message_safe=True) data.update({'form': partial_form()}) user.log_login_attempt(False) return jingo.render(request, template, data) rememberme = request.POST.get('rememberme', None) if rememberme: request.session.set_expiry(settings.SESSION_COOKIE_AGE) log.debug((u'User (%s) logged in successfully with ' '"remember me" set') % user) login_status = True if dont_redirect: # We're recalling the middleware to re-initialize amo_user ACLMiddleware().process_request(request) r = jingo.render(request, template, data) if login_status is not None: user.log_login_attempt(login_status) log_cef('Authentication Failure', 5, request, username=request.POST['username'], signature='AUTHFAIL', msg='The password was incorrect') return r
def browserid_authenticate(request, assertion, is_native=False, browserid_audience=get_audience): """ Verify a BrowserID login attempt. If the BrowserID assertion is good, but no account exists, create one. """ url = settings.BROWSERID_VERIFICATION_URL extra_params = None if is_native: # When persona is running native on B2G then we need to # verify assertions with the right service. # We also need to force the appropriate issuer # for potentially unverified emails. url = settings.NATIVE_BROWSERID_VERIFICATION_URL extra_params = { 'experimental_forceIssuer': settings.UNVERIFIED_ISSUER or False, 'experimental_allowUnverified': 'true' } log.debug('Verifying Persona at %s, audience: %s, ' 'extra_params: %s' % (url, browserid_audience, extra_params)) result = verify(assertion, browserid_audience, url=url, extra_params=extra_params) if not result: return None, _('Persona authentication failure.') if 'unverified-email' in result: email = result['unverified-email'] verified = False else: email = result['email'] verified = True try: profile = UserProfile.objects.filter(email=email)[0] except IndexError: profile = None if profile: if profile.is_verified and not verified: # An attempt to log in to a verified address with an unverified # assertion is a very bad thing. However, the same email address # can legitimately be used on the site on desktop and be verified # whilst be used on b2g and be unverified. We are forcing the # issuer, so this shouldn't be an issue. # # Blame kumar. Or cvan. Or deal with it. log.debug('Verified user %s attempted to log in with an ' 'unverified assertion!' % profile) else: profile.is_verified = verified profile.save() backend = 'django_browserid.auth.BrowserIDBackend' if getattr(profile.user, 'backend', None) != backend: profile.user.backend = backend profile.user.save() return profile, None username = autocreate_username(email.partition('@')[0]) source = (amo.LOGIN_SOURCE_MMO_BROWSERID if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID) profile = UserProfile.objects.create(username=username, email=email, source=source, display_name=username, is_verified=verified) profile.create_django_user( backend='django_browserid.auth.BrowserIDBackend') log_cef('New Account', 5, request, username=username, signature='AUTHNOTICE', msg='User created a new account (from Persona)') record_action('new-user', request) return profile, None