def send_email(self, request_ip): email = self.cleaned_data["email"] # on contrôle sur l'email ET sur l'IP if not send_mail_email_bucket.has_tokens(email.lower( )) or not send_mail_ip_bucket.has_tokens(request_ip): self.add_error( "email", forms.ValidationError(self.messages["rate_limited"], "rate_limited"), ) return False # On génère un short_code que la personne existe ou pas, pour éviter les timings attacks self.short_code, self.expiration = short_code_generator.generate_short_code( email) try: self.person = Person.objects.get_by_natural_key(email) except Person.DoesNotExist: self.person = None send_no_account_email.delay(email) else: send_login_email.apply_async( args=( self.cleaned_data["email"], self.short_code, self.expiration.timestamp(), ), expires=10 * 60, ) return True
def test_person_cannot_login_without_a_session_email(self): session = self.client.session session["login_email"] = None session.save() code, expiry = short_code_generator.generate_short_code( self.person.email) res = self.client.post(f"/api/connexion/code/", data={"code": code}) self.assertEqual(res.status_code, 405)
def test_person_cannot_login_if_short_code_is_not_valid( self, short_code_bucket, authenticate): session = self.client.session session["login_email"] = self.person.email session.save() code, expiry = short_code_generator.generate_short_code( self.person.email) res = self.client.post(f"/api/connexion/code/", data={"code": code}) self.assertEqual(res.status_code, 422) self.assertIn("code", res.data)
def test_checking_code(self): check_short_code_link = reverse("check_short_code") code, expiry = short_code_generator.generate_short_code(self.person.email) session = self.client.session session["login_email"] = self.person.email session.save() res = self.client.get(check_short_code_link + "?next=/profil/identite/") self.assertEqual(res.status_code, status.HTTP_200_OK) res = self.client.post(check_short_code_link, {"code": code}) self.assertRedirects(res, "/profil/identite/")
def test_email_is_debounced_if_login_succeeds(self): email = self.person.emails.get_by_natural_key(self.person.email) email.bounced = True email.save() session = self.client.session session["login_email"] = self.person.email session.save() code, expiry = short_code_generator.generate_short_code( self.person.email) res = self.client.post(f"/api/connexion/code/", data={"code": code}) self.assertEqual(res.status_code, 200) email = self.person.emails.get_by_natural_key(self.person.email) self.assertFalse(email.bounced)
def test_person_can_login_if_short_code_is_valid(self): session_res = self.client.get("/api/session/") self.assertIn("user", session_res.data) self.assertEqual(session_res.data["user"], False) session = self.client.session session["login_email"] = self.person.email session.save() code, expiry = short_code_generator.generate_short_code( self.person.email) res = self.client.post(f"/api/connexion/code/", data={"code": code}) self.assertEqual(res.status_code, 200) self.assertIn("lastLogin", res.data) session_res = self.client.get("/api/session/") self.assertIn("user", session_res.data) self.assertIn("email", session_res.data["user"]) self.assertEqual(session_res.data["user"]["email"], self.person.email)
def send_authentication_email(self, email): self.request.session["login_email"] = email short_code = None expiration = None try: Person.objects.get_by_natural_key(email) except Person.DoesNotExist: send_no_account_email.delay(email) else: short_code, expiration = short_code_generator.generate_short_code(email) send_login_email.apply_async( args=( email, short_code, expiration.timestamp(), ), expires=10 * 60, ) return short_code, expiration
def send_email(self): if not send_mail_bucket.has_tokens(self.person.pk): self.add_error( "email", forms.ValidationError(self.messages["rate_limited"], "rate_limited"), ) return False self.short_code, self.expiration = short_code_generator.generate_short_code( self.person.pk, meta={"email": self.cleaned_data["email"]}) send_login_email.apply_async( args=( self.cleaned_data["email"], self.short_code, self.expiration.timestamp(), ), expires=10 * 60, ) return True