diff --git a/zerver/forms.py b/zerver/forms.py
index 6b55b71ec8..9c34413382 100644
--- a/zerver/forms.py
+++ b/zerver/forms.py
@@ -210,8 +210,6 @@ class ZulipPasswordResetForm(PasswordResetForm):
subdomain = get_subdomain(request)
realm = get_realm(subdomain)
- if realm is None:
- raise ValidationError("Invalid realm")
if not email_auth_enabled(realm):
logging.info("Password reset attempted for %s even though password auth is disabled." % (email,))
diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py
index ee06c07369..1299ba7c79 100644
--- a/zerver/tests/test_signup.py
+++ b/zerver/tests/test_signup.py
@@ -227,19 +227,11 @@ class PasswordResetTest(ZulipTestCase):
def test_wrong_subdomain(self):
# type: () -> None
email = self.example_email("hamlet")
- string_id = 'hamlet'
- name = 'Hamlet'
- do_create_realm(
- string_id,
- name,
- restricted_to_domain=False,
- invite_required=False
- )
- with patch('zerver.forms.get_subdomain', return_value=string_id):
- # start the password reset process by supplying an email address
- result = self.client_post(
- '/accounts/password/reset/', {'email': email})
+ # start the password reset process by supplying an email address
+ result = self.client_post(
+ '/accounts/password/reset/', {'email': email},
+ subdomain="zephyr")
# check the redirect link telling you to check mail for password reset link
self.assertEqual(result.status_code, 302)
@@ -258,31 +250,22 @@ class PasswordResetTest(ZulipTestCase):
self.assertIn("hamlet@zulip.com does not have an active account in\nhttp://zephyr.testserver",
message.body)
- def test_correct_subdomain(self):
+ def test_invalid_subdomain(self):
# type: () -> None
email = self.example_email("hamlet")
- string_id = 'zulip'
- with patch('zerver.forms.get_subdomain', return_value=string_id):
- # start the password reset process by supplying an email address
- result = self.client_post(
- '/accounts/password/reset/', {'email': email})
+ # start the password reset process by supplying an email address
+ result = self.client_post(
+ '/accounts/password/reset/', {'email': email},
+ subdomain="invalid")
# check the redirect link telling you to check mail for password reset link
- self.assertEqual(result.status_code, 302)
- self.assertTrue(result["Location"].endswith(
- "/accounts/password/reset/done/"))
- result = self.client_get(result["Location"])
-
- self.assert_in_response("Check your email to finish the process.", result)
+ self.assertEqual(result.status_code, 200)
+ self.assert_in_success_response(["There is no Zulip organization hosted at this subdomain."],
+ result)
from django.core.mail import outbox
- self.assertEqual(len(outbox), 1)
- message = outbox.pop()
- self.assertIn("Zulip Account Security", message.from_email)
- self.assertIn(FromAddress.NOREPLY, message.from_email)
- self.assertIn("Psst. Word on the street is that you",
- message.body)
+ self.assertEqual(len(outbox), 0)
@override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',
'zproject.backends.ZulipDummyBackend'))
diff --git a/zerver/views/auth.py b/zerver/views/auth.py
index 874e8f01d8..f97f8d7b8a 100644
--- a/zerver/views/auth.py
+++ b/zerver/views/auth.py
@@ -5,6 +5,7 @@ from django.core.validators import validate_email
from django.contrib.auth import authenticate, get_backends
from django.contrib.auth.views import login as django_login_page, \
logout_then_login as django_logout_then_login
+from django.contrib.auth.views import password_reset as django_password_reset
from django.core.urlresolvers import reverse
from zerver.decorator import authenticated_json_post_view, require_post, \
process_client, do_login, log_view_func
@@ -22,7 +23,7 @@ from typing import Any, Dict, List, Optional, Tuple, Text
from confirmation.models import Confirmation, create_confirmation_link
from zerver.context_processors import zulip_default_context, get_realm_from_request
from zerver.forms import HomepageForm, OurAuthenticationForm, \
- WRONG_SUBDOMAIN_ERROR
+ WRONG_SUBDOMAIN_ERROR, ZulipPasswordResetForm
from zerver.lib.mobile_auth_otp import is_valid_otp, otp_encrypt_api_key
from zerver.lib.request import REQ, has_request_variables, JsonableError
from zerver.lib.response import json_success, json_error
@@ -760,3 +761,17 @@ def api_fetch_google_client_id(request):
def logout_then_login(request, **kwargs):
# type: (HttpRequest, **Any) -> HttpResponse
return django_logout_then_login(request, kwargs)
+
+def password_reset(request: HttpRequest, **kwargs: Any) -> HttpResponse:
+ realm = get_realm(get_subdomain(request))
+
+ if realm is None:
+ # If trying to get to password reset on a subdomain that
+ # doesn't exist, just go to find_account.
+ redirect_url = reverse('zerver.views.registration.find_account')
+ return HttpResponseRedirect(redirect_url)
+
+ return django_password_reset(request,
+ template_name='zerver/reset.html',
+ password_reset_form=ZulipPasswordResetForm,
+ post_reset_redirect='/accounts/password/reset/done/')
diff --git a/zproject/urls.py b/zproject/urls.py
index 8803c98ec8..3b604fa886 100644
--- a/zproject/urls.py
+++ b/zproject/urls.py
@@ -13,8 +13,8 @@ from zerver.lib.integrations import WEBHOOK_INTEGRATIONS
from zerver.webhooks import github_dispatcher
-from django.contrib.auth.views import (login, password_reset,
- password_reset_done, password_reset_confirm, password_reset_complete)
+from django.contrib.auth.views import (login, password_reset_done,
+ password_reset_confirm, password_reset_complete)
import zerver.tornado.views
import zerver.views
@@ -367,11 +367,8 @@ i18n_urls = [
zerver.views.zephyr.webathena_kerberos_login,
name='zerver.views.zephyr.webathena_kerberos_login'),
- url(r'^accounts/password/reset/$', password_reset,
- {'post_reset_redirect': '/accounts/password/reset/done/',
- 'template_name': 'zerver/reset.html',
- 'password_reset_form': zerver.forms.ZulipPasswordResetForm,
- }, name='django.contrib.auth.views.password_reset'),
+ url(r'^accounts/password/reset/$', zerver.views.auth.password_reset,
+ name='zerver.views.auth.password_reset'),
url(r'^accounts/password/reset/done/$', password_reset_done,
{'template_name': 'zerver/reset_emailed.html'}),
url(r'^accounts/password/reset/(?P[0-9A-Za-z]+)/(?P.+)/$',