registration: Create PreregistrationRealm object when creating realm.

This commit adds code to create PreregistrationRealm object when
creating realm and set it to the content_object field of
Confirmation object.
This commit is contained in:
Sahil Batra 2023-03-03 16:28:00 +05:30 committed by Tim Abbott
parent 80b00933b1
commit 54771cfe94
8 changed files with 324 additions and 79 deletions

View File

@ -302,7 +302,15 @@ class TestSupportEndpoint(ZulipTestCase):
check_zulip_realm_query_result(result)
email = self.nonreg_email("alice")
self.client_post("/new/", {"email": email})
self.client_post(
"/new/",
{
"email": email,
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
result = get_check_query_result(email, 1)
check_realm_creation_query_result(result, email)

View File

@ -35,6 +35,7 @@ from zerver.lib.subdomains import get_subdomain_from_hostname
from zerver.lib.validator import check_bool, check_string_in, to_decimal, to_non_negative_int
from zerver.models import (
MultiuseInvite,
PreregistrationRealm,
PreregistrationUser,
Realm,
RealmReactivationStatus,
@ -303,11 +304,20 @@ def support(
user.id for user in PreregistrationUser.objects.filter(email__in=key_words)
]
confirmations += get_confirmations(
[Confirmation.USER_REGISTRATION, Confirmation.INVITATION, Confirmation.REALM_CREATION],
[Confirmation.USER_REGISTRATION, Confirmation.INVITATION],
preregistration_user_ids,
hostname=request.get_host(),
)
preregistration_realm_ids = [
user.id for user in PreregistrationRealm.objects.filter(email__in=key_words)
]
confirmations += get_confirmations(
[Confirmation.REALM_CREATION],
preregistration_realm_ids,
hostname=request.get_host(),
)
multiuse_invite_ids = [
invite.id for invite in MultiuseInvite.objects.filter(realm__in=realms)
]

View File

@ -22,6 +22,7 @@ from zerver.lib.types import UnspecifiedValue
from zerver.models import (
EmailChangeStatus,
MultiuseInvite,
PreregistrationRealm,
PreregistrationUser,
Realm,
RealmReactivationStatus,
@ -56,6 +57,7 @@ def generate_key() -> str:
ConfirmationObjT = Union[
MultiuseInvite,
PreregistrationRealm,
PreregistrationUser,
EmailChangeStatus,
UserProfile,
@ -114,12 +116,17 @@ def create_confirmation_link(
*,
validity_in_minutes: Union[Optional[int], UnspecifiedValue] = UnspecifiedValue(),
url_args: Mapping[str, str] = {},
realm_creation: bool = False,
) -> str:
# validity_in_minutes is an override for the default values which are
# determined by the confirmation_type - its main purpose is for use
# in tests which may want to have control over the exact expiration time.
key = generate_key()
realm = obj.realm
if realm_creation:
realm = None
else:
assert not isinstance(obj, PreregistrationRealm)
realm = obj.realm
current_time = timezone_now()
expiry_date = None

View File

@ -24,7 +24,7 @@ from zerver.lib.rate_limiter import (
)
from zerver.lib.test_classes import ZulipTestCase
from zerver.lib.zephyr import compute_mit_user_fullname
from zerver.models import PushDeviceToken, UserProfile
from zerver.models import PushDeviceToken, Realm, UserProfile
if settings.ZILENCER_ENABLED:
from zilencer.models import RateLimitedRemoteZulipServer, RemoteZulipServer
@ -223,7 +223,15 @@ class RateLimitTests(ZulipTestCase):
def test_create_realm_rate_limiting(self) -> None:
with self.settings(OPEN_REALM_CREATION=True):
self.do_test_hit_ratelimits(
lambda: self.client_post("/new/", {"email": "new@zulip.com"}),
lambda: self.client_post(
"/new/",
{
"email": "new@zulip.com",
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
),
is_json=False,
)
@ -288,7 +296,15 @@ class RateLimitTests(ZulipTestCase):
nonlocal request_count
request_count += 1
if request_count % 2 == 1:
return self.client_post("/new/", {"email": "new@zulip.com"})
return self.client_post(
"/new/",
{
"email": "new@zulip.com",
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
else:
return self.client_post("/accounts/find/", {"emails": "new@zulip.com"})

View File

@ -300,7 +300,15 @@ class TestGenerateRealmCreationLink(ZulipTestCase):
# Enter email
with self.assertRaises(Realm.DoesNotExist):
get_realm("test")
result = self.client_post(generated_link, {"email": email})
result = self.client_post(
generated_link,
{
"email": email,
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(re.search(r"/accounts/do_confirm/\w+$", result["Location"]))
@ -317,7 +325,15 @@ class TestGenerateRealmCreationLink(ZulipTestCase):
email = "user1@test.com"
generated_link = generate_realm_creation_url(by_admin=False)
result = self.client_post(generated_link, {"email": email})
result = self.client_post(
generated_link,
{
"email": email,
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
self.assertEqual(result.status_code, 302)
self.assertEqual(
f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}", result["Location"]

View File

@ -1257,7 +1257,15 @@ class RealmCreationTest(ZulipTestCase):
get_realm(string_id)
# Create new realm with the email
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": org_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1266,6 +1274,10 @@ class RealmCreationTest(ZulipTestCase):
)
result = self.client_get(result["Location"])
self.assert_in_response("Check your email", result)
prereg_realm = PreregistrationRealm.objects.get(email=email)
self.assertEqual(prereg_realm.name, "Zulip Test")
self.assertEqual(prereg_realm.org_type, Realm.ORG_TYPES["business"]["id"])
self.assertEqual(prereg_realm.string_id, string_id)
# Check confirmation email has the correct subject and body, extract
# confirmation link and visit it
@ -1347,7 +1359,15 @@ class RealmCreationTest(ZulipTestCase):
)
def test_create_realm_as_system_bot(self) -> None:
result = self.client_post("/new/", {"email": "notification-bot@zulip.com"})
result = self.client_post(
"/new/",
{
"email": "notification-bot@zulip.com",
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
self.assertEqual(result.status_code, 200)
self.assert_in_response("notification-bot@zulip.com is reserved for system bots", result)
@ -1360,7 +1380,15 @@ class RealmCreationTest(ZulipTestCase):
with self.settings(OPEN_REALM_CREATION=False):
# Create new realm with the email, but no creation key.
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
self.assertEqual(result.status_code, 200)
self.assert_in_response("Organization creation link required", result)
@ -1376,7 +1404,15 @@ class RealmCreationTest(ZulipTestCase):
get_realm(string_id)
# Create new realm with the email
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1420,7 +1456,15 @@ class RealmCreationTest(ZulipTestCase):
get_realm(string_id)
# Create new realm with the email
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1467,7 +1511,15 @@ class RealmCreationTest(ZulipTestCase):
get_realm(string_id)
# Create new realm with the email
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1525,7 +1577,15 @@ class RealmCreationTest(ZulipTestCase):
get_realm(string_id)
# Create new realm with the email
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1568,7 +1628,15 @@ class RealmCreationTest(ZulipTestCase):
realm_name = "Test"
# Create new realm with the email
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1607,7 +1675,15 @@ class RealmCreationTest(ZulipTestCase):
realm_name = "Test"
# Create new realm with the email
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1649,7 +1725,15 @@ class RealmCreationTest(ZulipTestCase):
with self.assertRaises(Realm.DoesNotExist):
get_realm(string_id)
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1701,7 +1785,15 @@ class RealmCreationTest(ZulipTestCase):
get_realm(second_string_id)
# Now we pre-generate two realm creation links
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": first_realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": first_string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1714,7 +1806,15 @@ class RealmCreationTest(ZulipTestCase):
self.assertEqual(PreregistrationUser.objects.filter(email=email, status=0).count(), 1)
# Get a second realm creation link.
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": second_realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": second_string_id,
},
)
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
@ -1768,10 +1868,26 @@ class RealmCreationTest(ZulipTestCase):
@override_settings(OPEN_REALM_CREATION=True)
def test_invalid_email_signup(self) -> None:
result = self.client_post("/new/", {"email": "<foo"})
result = self.client_post(
"/new/",
{
"email": "<foo",
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
self.assert_in_response("Please use your real email address.", result)
result = self.client_post("/new/", {"email": "foo\x00bar"})
result = self.client_post(
"/new/",
{
"email": "foo\x00bar",
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
self.assert_in_response("Please use your real email address.", result)
@override_settings(OPEN_REALM_CREATION=True)
@ -1785,11 +1901,6 @@ class RealmCreationTest(ZulipTestCase):
email = "user1@test.com"
realm_name = "Test"
result = self.client_post("/new/", {"email": email})
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
errors = {
"id": "length 3 or greater",
"-id": "cannot start or end with a",
@ -1802,12 +1913,31 @@ class RealmCreationTest(ZulipTestCase):
"zephyr": "unavailable",
}
for string_id, error_msg in errors.items():
result = self.submit_reg_form_for_user(
email, password, realm_subdomain=string_id, realm_name=realm_name
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": string_id,
},
)
self.assert_in_response(error_msg, result)
# test valid subdomain
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "a-0",
},
)
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
result = self.submit_reg_form_for_user(
email, password, realm_subdomain="a-0", realm_name=realm_name
)
@ -1821,16 +1951,16 @@ class RealmCreationTest(ZulipTestCase):
realm = get_realm("zulip")
do_change_realm_subdomain(realm, "new-name", acting_user=None)
password = "test"
email = "user1@test.com"
realm_name = "Test"
result = self.client_post("/new/", {"email": email})
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
result = self.submit_reg_form_for_user(
email, password, realm_subdomain="zulip", realm_name=realm_name
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": "Test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "test",
},
)
self.assert_in_response("Subdomain unavailable. Please choose a different one.", result)
@ -1840,19 +1970,33 @@ class RealmCreationTest(ZulipTestCase):
email = "user1@test.com"
realm_name = "Test"
result = self.client_post("/new/", {"email": email})
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
# test root domain will fail with ROOT_DOMAIN_LANDING_PAGE
with self.settings(ROOT_DOMAIN_LANDING_PAGE=True):
result = self.submit_reg_form_for_user(
email, password, realm_subdomain="", realm_name=realm_name
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "",
},
)
self.assert_in_response("unavailable", result)
# test valid use of root domain
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "",
},
)
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
result = self.submit_reg_form_for_user(
email, password, realm_subdomain="", realm_name=realm_name
)
@ -1867,23 +2011,35 @@ class RealmCreationTest(ZulipTestCase):
email = "user1@test.com"
realm_name = "Test"
result = self.client_post("/new/", {"email": email})
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
# test root domain will fail with ROOT_DOMAIN_LANDING_PAGE
with self.settings(ROOT_DOMAIN_LANDING_PAGE=True):
result = self.submit_reg_form_for_user(
email,
password,
realm_subdomain="abcdef",
realm_in_root_domain="true",
realm_name=realm_name,
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "abcdef",
"realm_in_root_domain": "true",
},
)
self.assert_in_response("unavailable", result)
# test valid use of root domain
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "abcdef",
"realm_in_root_domain": "true",
},
)
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
result = self.submit_reg_form_for_user(
email,
password,
@ -2043,7 +2199,15 @@ class UserSignUpTest(ZulipTestCase):
)
with smtp_mock, self.assertLogs(level="ERROR") as m:
result = self.client_post("/new/", {"email": email})
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": "Zulip test",
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": "zuliptest",
},
)
self._assert_redirected_to(result, "/config-error/smtp")
self.assertEqual(m.output, ["ERROR:root:Error in create_realm"])
@ -2647,27 +2811,22 @@ class UserSignUpTest(ZulipTestCase):
"""
realm = get_realm("zulip")
password = "test"
email = self.example_email("iago")
realm_name = "Test"
result = self.client_post("/new/", {"email": email})
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
result = self.submit_reg_form_for_user(
email,
password,
# Subdomain is already used, by construction.
realm_subdomain=realm.string_id,
realm_name=realm_name,
source_realm_id=str(realm.id),
result = self.client_post(
"/new/",
{
"email": email,
"realm_name": realm_name,
"realm_type": Realm.ORG_TYPES["business"]["id"],
"realm_subdomain": realm.string_id,
},
)
self.assert_in_success_response(
[
"Subdomain unavailable. Please choose a different one.",
"Zulip Dev\n",
'value="test"',
'value="Test"',
'name="realm_name"',
],
result,

View File

@ -70,6 +70,7 @@ from zerver.lib.utils import has_api_key_format
from zerver.lib.validator import check_bool, validate_login_email
from zerver.models import (
MultiuseInvite,
PreregistrationRealm,
PreregistrationUser,
Realm,
UserProfile,
@ -137,6 +138,20 @@ def create_preregistration_user(
)
def create_preregistration_realm(
email: str,
name: str,
string_id: str,
org_type: int,
) -> PreregistrationRealm:
return PreregistrationRealm.objects.create(
email=email,
name=name,
string_id=string_id,
org_type=org_type,
)
def maybe_send_to_registration(
request: HttpRequest,
email: str,

View File

@ -77,6 +77,7 @@ from zerver.models import (
name_changes_disabled,
)
from zerver.views.auth import (
create_preregistration_realm,
create_preregistration_user,
finish_desktop_flow,
finish_mobile_flow,
@ -586,7 +587,6 @@ def prepare_activation_url(
session: SessionBase,
*,
realm: Optional[Realm],
realm_creation: bool = False,
streams: Optional[Iterable[Stream]] = None,
invited_as: Optional[int] = None,
multiuse_invite: Optional[MultiuseInvite] = None,
@ -595,9 +595,7 @@ def prepare_activation_url(
Send an email with a confirmation link to the provided e-mail so the user
can complete their registration.
"""
prereg_user = create_preregistration_user(
email, realm, realm_creation, multiuse_invite=multiuse_invite
)
prereg_user = create_preregistration_user(email, realm, multiuse_invite=multiuse_invite)
if streams is not None:
prereg_user.streams.set(streams)
@ -607,11 +605,24 @@ def prepare_activation_url(
prereg_user.save()
confirmation_type = Confirmation.USER_REGISTRATION
if realm_creation:
confirmation_type = Confirmation.REALM_CREATION
activation_url = create_confirmation_link(prereg_user, confirmation_type)
if settings.DEVELOPMENT and realm_creation:
return activation_url
def prepare_realm_activation_url(
email: str,
session: SessionBase,
realm_name: str,
string_id: str,
org_type: int,
) -> str:
prereg_realm = create_preregistration_realm(email, realm_name, string_id, org_type)
activation_url = create_confirmation_link(
prereg_realm, Confirmation.REALM_CREATION, realm_creation=True
)
if settings.DEVELOPMENT:
session["confirmation_key"] = {"confirmation_key": activation_url.split("/")[-1]}
return activation_url
@ -677,8 +688,11 @@ def create_realm(request: HttpRequest, creation_key: Optional[str] = None) -> Ht
)
email = form.cleaned_data["email"]
activation_url = prepare_activation_url(
email, request.session, realm=None, realm_creation=True
realm_name = form.cleaned_data["realm_name"]
realm_type = form.cleaned_data["realm_type"]
realm_subdomain = form.cleaned_data["realm_subdomain"]
activation_url = prepare_realm_activation_url(
email, request.session, realm_name, realm_subdomain, realm_type
)
if key_record is not None and key_record.presume_email_valid:
# The user has a token created from the server command line;