registration: Allow import owner to switch to one of imported users.

In case we cannot find a user with email matching with the one
used for preregistration, we ask the import owner which user they
really are.
This commit is contained in:
Aman Agrawal 2024-11-09 11:37:53 +05:30
parent 24a84f7922
commit c5da750181
4 changed files with 124 additions and 1 deletions

View File

@ -0,0 +1,49 @@
{% extends "zerver/portico_signup.html" %}
{% set entrypoint = "register" %}
{% block title %}
<title>{{ _("Finalize organization import") }} | Zulip</title>
{% endblock %}
{% block portico_content %}
<div class="app register-page">
<div class="app-main register-page-container new-style flex full-page center">
<div class="register-form left" id="realm-import-post-process">
<div class="lead">
<h1 class="get-started">{{ _("Organization import completed!") }}</h1>
</div>
<div class="white-box">
<form method="post" class="form-inline" action="{{ url('realm_import_post_process', args=[key]) }}">
{{ csrf_input }}
<div class="input-box no-validation">
<input type='hidden' name='key' value='{{ key }}' />
</div>
<div class="input-box slack-import-extra-info">
<div class="not-editable-realm-field">
{% trans %}
No account in the imported data matched the email address you've verified with Zulip ({{ email }}).
Select a user account from the data export to associate your email address with, or create a new account if you didn't have an account in the original export.
{% endtrans %}
</div>
</div>
<div class="input-box">
<label for="email" class="inline-block label-title">Select your account</label>
<select id="realm-import-owner" name="email" class="required">
{% for user in users %}
<option value="{{ user.delivery_email }}">
{{ user.full_name }} ({{user.delivery_email}})
</option>
{% endfor %}
</select>
</div>
<div class="input-box">
<button type="submit" class="register-button">
{{ _("Confirm") }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -318,6 +318,10 @@ class HomepageForm(forms.Form):
return email
class ImportRealmOwnerSelectionForm(forms.Form):
email = forms.EmailField(validators=[email_not_system_bot])
class RealmCreationForm(RealmDetailsForm):
# This form determines whether users can create a new realm.
email = forms.EmailField(validators=[email_not_system_bot, email_is_not_disposable])

View File

@ -18,10 +18,12 @@ from django.shortcuts import redirect, render
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.translation import get_language
from django.utils.translation import gettext as _
from django.views.defaults import server_error
from django_auth_ldap.backend import LDAPBackend, _LDAPUser
from pydantic import Json, NonNegativeInt, StringConstraints
from confirmation import settings as confirmation_settings
from confirmation.models import (
Confirmation,
ConfirmationKeyError,
@ -49,12 +51,13 @@ from zerver.decorator import add_google_analytics, do_login, require_post
from zerver.forms import (
FindMyTeamForm,
HomepageForm,
ImportRealmOwnerSelectionForm,
RealmCreationForm,
RealmRedirectForm,
RegistrationForm,
)
from zerver.lib.email_validation import email_allowed_for_realm, validate_email_not_already_in_realm
from zerver.lib.exceptions import RateLimitedError
from zerver.lib.exceptions import JsonableError, RateLimitedError
from zerver.lib.i18n import (
get_browser_language_code,
get_default_language_for_new_user,
@ -105,6 +108,7 @@ from zerver.views.auth import (
create_preregistration_user,
finish_desktop_flow,
finish_mobile_flow,
get_safe_redirect_to,
redirect_and_log_into_subdomain,
redirect_to_deactivation_notice,
)
@ -877,6 +881,66 @@ def redirect_to_email_login_url(email: str) -> HttpResponseRedirect:
return HttpResponseRedirect(redirect_url)
@transaction.atomic(durable=True)
def realm_import_post_process(
request: HttpRequest,
confirmation_key: str,
) -> HttpResponse:
try:
preregistration_realm = get_object_from_key(
confirmation_key,
[Confirmation.REALM_CREATION],
mark_object_used=False,
allow_used=True,
)
except ConfirmationKeyError as exception:
return render_confirmation_key_error(request, exception)
assert isinstance(preregistration_realm, PreregistrationRealm)
try:
realm = Realm.objects.get(string_id=preregistration_realm.string_id)
except Realm.DoesNotExist:
# If we cannot find the realm, likely means there was something
# wrong with the import process. Revoke the confirmation key to
# force user to restart the process.
preregistration_realm.status = confirmation_settings.STATUS_REVOKED
preregistration_realm.save(update_fields=["status"])
return render_confirmation_key_error(
request, ConfirmationKeyError(ConfirmationKeyError.EXPIRED)
)
if not preregistration_realm.data_import_metadata["no_user_matching_email"]:
return HttpResponseRedirect(get_safe_redirect_to(reverse("login"), realm.url))
if request.method == "POST":
form = ImportRealmOwnerSelectionForm(request.POST)
if form.is_valid():
email = form.cleaned_data["email"]
user = get_user_by_delivery_email(email, realm)
user.delivery_email = preregistration_realm.email
user.role = UserProfile.ROLE_REALM_OWNER
user.save(update_fields=["delivery_email", "role"])
preregistration_realm.status = confirmation_settings.STATUS_USED
preregistration_realm.created_realm = realm
preregistration_realm.data_import_metadata["no_user_matching_email"] = False
preregistration_realm.save()
return HttpResponseRedirect(get_safe_redirect_to(reverse("login"), realm.url))
users = UserProfile.objects.filter(realm=realm, is_bot=False)
context = {
"users": users,
"email": preregistration_realm.email,
"key": confirmation_key,
}
return TemplateResponse(
request,
"zerver/realm_import_post_process.html",
context,
)
@add_google_analytics
def create_realm(request: HttpRequest, creation_key: str | None = None) -> HttpResponse:
try:

View File

@ -143,6 +143,7 @@ from zerver.views.registration import (
find_account,
get_prereg_key_and_redirect,
new_realm_send_confirm,
realm_import_post_process,
realm_redirect,
realm_register,
signup_send_confirm,
@ -593,6 +594,11 @@ i18n_urls = [
),
path("accounts/register/", accounts_register, name="accounts_register"),
path("realm/register/", realm_register, name="realm_register"),
path(
"realm/import/post_process/<confirmation_key>",
realm_import_post_process,
name="realm_import_post_process",
),
path(
"accounts/do_confirm/<confirmation_key>",
get_prereg_key_and_redirect,