def accounts_home( request: HttpRequest, multiuse_object_key: str = "", multiuse_object: Optional[MultiuseInvite] = None) -> HttpResponse: try: realm = get_realm(get_subdomain(request)) except Realm.DoesNotExist: return HttpResponseRedirect( reverse('zerver.views.registration.find_account')) if realm.deactivated: return redirect_to_deactivation_notice() from_multiuse_invite = False streams_to_subscribe = None invited_as = None if multiuse_object: realm = multiuse_object.realm streams_to_subscribe = multiuse_object.streams.all() from_multiuse_invite = True invited_as = multiuse_object.invited_as if request.method == 'POST': form = HomepageForm(request.POST, realm=realm, from_multiuse_invite=from_multiuse_invite) if form.is_valid(): email = form.cleaned_data['email'] activation_url = prepare_activation_url( email, request, streams=streams_to_subscribe, invited_as=invited_as) try: send_confirm_registration_email(email, activation_url, request.LANGUAGE_CODE, realm=realm) except smtplib.SMTPException as e: logging.error('Error in accounts_home: %s', str(e)) return HttpResponseRedirect("/config-error/smtp") return HttpResponseRedirect( reverse('signup_send_confirm', kwargs={'email': email})) email = request.POST['email'] try: validate_email_not_already_in_realm(realm, email) except ValidationError: return redirect_to_email_login_url(email) else: form = HomepageForm(realm=realm) context = login_context(request) context.update({ 'form': form, 'current_url': request.get_full_path, 'multiuse_object_key': multiuse_object_key, 'from_multiuse_invite': from_multiuse_invite }) return render(request, 'zerver/accounts_home.html', context=context)
def api_get_server_settings(request: HttpRequest) -> HttpResponse: # Log which client is making this request. process_client(request, request.user, skip_update_user_activity=True) result = dict( authentication_methods=get_auth_backends_data(request), zulip_version=ZULIP_VERSION, zulip_feature_level=API_FEATURE_LEVEL, push_notifications_enabled=push_notifications_enabled(), is_incompatible=check_server_incompatibility(request), ) context = zulip_default_context(request) context.update(login_context(request)) # IMPORTANT NOTE: # realm_name, realm_icon, etc. are not guaranteed to appear in the response. # * If they do, that means the server URL has only one realm on it # * If they don't, the server has multiple realms, and it's not clear which is # the requested realm, so we can't send back these data. for settings_item in [ "email_auth_enabled", "require_email_format_usernames", "realm_uri", "realm_name", "realm_icon", "realm_description", "external_authentication_methods", ]: if context[settings_item] is not None: result[settings_item] = context[settings_item] return json_success(result)
def login_page(request: HttpRequest, **kwargs: Any) -> HttpResponse: # To support previewing the Zulip login pages, we have a special option # that disables the default behavior of redirecting logged-in users to the # logged-in app. is_preview = 'preview' in request.GET if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: if request.user and request.user.is_verified(): return HttpResponseRedirect(request.user.realm.uri) elif request.user.is_authenticated and not is_preview: return HttpResponseRedirect(request.user.realm.uri) if is_subdomain_root_or_alias(request) and settings.ROOT_DOMAIN_LANDING_PAGE: redirect_url = reverse('zerver.views.registration.realm_redirect') if request.GET: redirect_url = "{}?{}".format(redirect_url, request.GET.urlencode()) return HttpResponseRedirect(redirect_url) realm = get_realm_from_request(request) if realm and realm.deactivated: return redirect_to_deactivation_notice() extra_context = kwargs.pop('extra_context', {}) if dev_auth_enabled() and kwargs.get("template_name") == "zerver/dev_login.html": if 'new_realm' in request.POST: try: realm = get_realm(request.POST['new_realm']) except Realm.DoesNotExist: realm = None add_dev_login_context(realm, extra_context) if realm and 'new_realm' in request.POST: # If we're switching realms, redirect to that realm, but # only if it actually exists. return HttpResponseRedirect(realm.uri) if 'username' in request.POST: extra_context['email'] = request.POST['username'] extra_context.update(login_context(request)) if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: return start_two_factor_auth(request, extra_context=extra_context, **kwargs) try: template_response = DjangoLoginView.as_view( authentication_form=OurAuthenticationForm, extra_context=extra_context, **kwargs)(request) except ZulipLDAPConfigurationError as e: assert len(e.args) > 1 return redirect_to_misconfigured_ldap_notice(e.args[1]) if isinstance(template_response, SimpleTemplateResponse): # Only those responses that are rendered using a template have # context_data attribute. This attribute doesn't exist otherwise. It is # added in SimpleTemplateResponse class, which is a derived class of # HttpResponse. See django.template.response.SimpleTemplateResponse, # https://github.com/django/django/blob/master/django/template/response.py#L19. update_login_page_context(request, template_response.context_data) return template_response
def accounts_home( request: HttpRequest, multiuse_object_key: str = "", multiuse_object: Optional[MultiuseInvite] = None, ) -> HttpResponse: try: realm = get_realm(get_subdomain(request)) except Realm.DoesNotExist: return HttpResponseRedirect(reverse(find_account)) if realm.deactivated: return redirect_to_deactivation_notice() from_multiuse_invite = False streams_to_subscribe = None invited_as = None if multiuse_object: realm = multiuse_object.realm streams_to_subscribe = multiuse_object.streams.all() from_multiuse_invite = True invited_as = multiuse_object.invited_as if request.method == "POST": form = HomepageForm(request.POST, realm=realm, from_multiuse_invite=from_multiuse_invite) if form.is_valid(): email = form.cleaned_data["email"] try: validate_email_not_already_in_realm(realm, email) except ValidationError: return redirect_to_email_login_url(email) activation_url = prepare_activation_url( email, request, streams=streams_to_subscribe, invited_as=invited_as ) try: send_confirm_registration_email( email, activation_url, request.LANGUAGE_CODE, realm=realm ) except EmailNotDeliveredException: logging.error("Error in accounts_home") return HttpResponseRedirect("/config-error/smtp") return HttpResponseRedirect(reverse("signup_send_confirm", kwargs={"email": email})) else: form = HomepageForm(realm=realm) context = login_context(request) context.update( form=form, current_url=request.get_full_path, multiuse_object_key=multiuse_object_key, from_multiuse_invite=from_multiuse_invite, ) return render(request, "zerver/accounts_home.html", context=context)
def maybe_send_to_registration( request: HttpRequest, email: str, full_name: str = "", mobile_flow_otp: Optional[str] = None, desktop_flow_otp: Optional[str] = None, is_signup: bool = False, password_required: bool = True, multiuse_object_key: str = "", full_name_validated: bool = False, ) -> HttpResponse: """Given a successful authentication for an email address (i.e. we've confirmed the user controls the email address) that does not currently have a Zulip account in the target realm, send them to the registration flow or the "continue to registration" flow, depending on is_signup, whether the email address can join the organization (checked in HomepageForm), and similar details. """ # In the desktop and mobile registration flows, the sign up # happens in the browser so the user can use their # already-logged-in social accounts. Then at the end, with the # user account created, we pass the appropriate data to the app # via e.g. a `zulip://` redirect. We store the OTP keys for the # mobile/desktop flow in the session with 1-hour expiry, because # we want this configuration of having a successful authentication # result in being logged into the app to persist if the user makes # mistakes while trying to authenticate (E.g. clicks the wrong # Google account, hits back, etc.) during a given browser session, # rather than just logging into the webapp in the target browser. # # We can't use our usual pre-account-creation state storage # approach of putting something in PreregistrationUser, because # that would apply to future registration attempts on other # devices, e.g. just creating an account on the web on their laptop. assert not (mobile_flow_otp and desktop_flow_otp) if mobile_flow_otp: set_expirable_session_var( request.session, "registration_mobile_flow_otp", mobile_flow_otp, expiry_seconds=3600 ) elif desktop_flow_otp: set_expirable_session_var( request.session, "registration_desktop_flow_otp", desktop_flow_otp, expiry_seconds=3600 ) if multiuse_object_key: from_multiuse_invite = True multiuse_obj = Confirmation.objects.get(confirmation_key=multiuse_object_key).content_object realm = multiuse_obj.realm invited_as = multiuse_obj.invited_as else: from_multiuse_invite = False multiuse_obj = None try: realm = get_realm(get_subdomain(request)) except Realm.DoesNotExist: realm = None invited_as = PreregistrationUser.INVITE_AS["MEMBER"] form = HomepageForm({"email": email}, realm=realm, from_multiuse_invite=from_multiuse_invite) if form.is_valid(): # If the email address is allowed to sign up for an account in # this organization, construct a PreregistrationUser and # Confirmation objects, and then send the user to account # creation or confirm-continue-registration depending on # is_signup. try: prereg_user = filter_to_valid_prereg_users( PreregistrationUser.objects.filter(email__iexact=email, realm=realm) ).latest("invited_at") # password_required and full_name data passed here as argument should take precedence # over the defaults with which the existing PreregistrationUser that we've just fetched # was created. prereg_user.password_required = password_required update_fields = ["password_required"] if full_name: prereg_user.full_name = full_name prereg_user.full_name_validated = full_name_validated update_fields.extend(["full_name", "full_name_validated"]) prereg_user.save(update_fields=update_fields) except PreregistrationUser.DoesNotExist: prereg_user = create_preregistration_user( email, request, password_required=password_required, full_name=full_name, full_name_validated=full_name_validated, ) if multiuse_obj is not None: request.session.modified = True streams_to_subscribe = list(multiuse_obj.streams.all()) prereg_user.streams.set(streams_to_subscribe) prereg_user.invited_as = invited_as prereg_user.save() confirmation_link = create_confirmation_link(prereg_user, Confirmation.USER_REGISTRATION) if is_signup: return redirect(confirmation_link) context = {"email": email, "continue_link": confirmation_link, "full_name": full_name} return render(request, "zerver/confirm_continue_registration.html", context=context) # This email address it not allowed to join this organization, so # just send the user back to the registration page. url = reverse("register") context = login_context(request) extra_context: Mapping[str, Any] = { "form": form, "current_url": lambda: url, "from_multiuse_invite": from_multiuse_invite, "multiuse_object_key": multiuse_object_key, "mobile_flow_otp": mobile_flow_otp, "desktop_flow_otp": desktop_flow_otp, } context.update(extra_context) return render(request, "zerver/accounts_home.html", context=context)
def maybe_send_to_registration( request: HttpRequest, email: str, full_name: str = '', is_signup: bool = False, password_required: bool = True, multiuse_object_key: str = '', full_name_validated: bool = False) -> HttpResponse: """Given a successful authentication for an email address (i.e. we've confirmed the user controls the email address) that does not currently have a Zulip account in the target realm, send them to the registration flow or the "continue to registration" flow, depending on is_signup, whether the email address can join the organization (checked in HomepageForm), and similar details. """ if multiuse_object_key: from_multiuse_invite = True multiuse_obj = Confirmation.objects.get( confirmation_key=multiuse_object_key).content_object realm = multiuse_obj.realm invited_as = multiuse_obj.invited_as else: from_multiuse_invite = False multiuse_obj = None try: realm = get_realm(get_subdomain(request)) except Realm.DoesNotExist: realm = None invited_as = PreregistrationUser.INVITE_AS['MEMBER'] form = HomepageForm({'email': email}, realm=realm, from_multiuse_invite=from_multiuse_invite) if form.is_valid(): # If the email address is allowed to sign up for an account in # this organization, construct a PreregistrationUser and # Confirmation objects, and then send the user to account # creation or confirm-continue-registration depending on # is_signup. try: prereg_user = PreregistrationUser.objects.filter( email__iexact=email, realm=realm).latest("invited_at") # password_required and full_name data passed here as argument should take precedence # over the defaults with which the existing PreregistrationUser that we've just fetched # was created. prereg_user.password_required = password_required update_fields = ["password_required"] if full_name: prereg_user.full_name = full_name prereg_user.full_name_validated = full_name_validated update_fields.extend(["full_name", "full_name_validated"]) prereg_user.save(update_fields=update_fields) except PreregistrationUser.DoesNotExist: prereg_user = create_preregistration_user( email, request, password_required=password_required, full_name=full_name, full_name_validated=full_name_validated) if multiuse_obj is not None: request.session.modified = True streams_to_subscribe = list(multiuse_obj.streams.all()) prereg_user.streams.set(streams_to_subscribe) prereg_user.invited_as = invited_as prereg_user.save() # We want to create a confirmation link to create an account # in the current realm, i.e. one with a hostname of # realm.host. For the Apache REMOTE_USER_SSO auth code path, # this is preferable over realm.get_host() because the latter # contains the port number of the Apache instance and we want # to send the user back to nginx. But if we're in the realm # creation code path, there might not be a realm yet, so we # have to use request.get_host(). if realm is not None: host = realm.host else: host = request.get_host() confirmation_link = create_confirmation_link( prereg_user, host, Confirmation.USER_REGISTRATION) if is_signup: return redirect(confirmation_link) context = { 'email': email, 'continue_link': confirmation_link, 'full_name': full_name } return render(request, 'zerver/confirm_continue_registration.html', context=context) # This email address it not allowed to join this organization, so # just send the user back to the registration page. url = reverse('register') context = login_context(request) extra_context = { 'form': form, 'current_url': lambda: url, 'from_multiuse_invite': from_multiuse_invite, 'multiuse_object_key': multiuse_object_key } # type: Mapping[str, Any] context.update(extra_context) return render(request, 'zerver/accounts_home.html', context=context)
def maybe_send_to_registration(request: HttpRequest, email: str, full_name: str = '', is_signup: bool = False, password_required: bool = True, multiuse_object_key: str = '') -> HttpResponse: """Given a successful authentication for an email address (i.e. we've confirmed the user controls the email address) that does not currently have a Zulip account in the target realm, send them to the registration flow or the "continue to registration" flow, depending on is_signup, whether the email address can join the organization (checked in HomepageForm), and similar details. """ realm = get_realm(get_subdomain(request)) from_multiuse_invite = False multiuse_obj = None streams_to_subscribe = None invited_as = PreregistrationUser.INVITE_AS['MEMBER'] if multiuse_object_key: from_multiuse_invite = True multiuse_obj = Confirmation.objects.get( confirmation_key=multiuse_object_key).content_object realm = multiuse_obj.realm streams_to_subscribe = multiuse_obj.streams.all() invited_as = multiuse_obj.invited_as form = HomepageForm({'email': email}, realm=realm, from_multiuse_invite=from_multiuse_invite) if form.is_valid(): # If the email address is allowed to sign up for an account in # this organization, construct a PreregistrationUser and # Confirmation objects, and then send the user to account # creation or confirm-continue-registration depending on # is_signup. prereg_user = None if settings.ONLY_SSO: try: prereg_user = PreregistrationUser.objects.filter( email__iexact=email, realm=realm).latest("invited_at") except PreregistrationUser.DoesNotExist: prereg_user = create_preregistration_user( email, request, password_required=password_required) else: prereg_user = create_preregistration_user( email, request, password_required=password_required) if multiuse_object_key: request.session.modified = True if streams_to_subscribe is not None: prereg_user.streams.set(streams_to_subscribe) prereg_user.invited_as = invited_as prereg_user.save() confirmation_link = create_confirmation_link( prereg_user, request.get_host(), Confirmation.USER_REGISTRATION) if is_signup: return redirect(confirmation_link) context = { 'email': email, 'continue_link': confirmation_link, 'full_name': full_name } return render(request, 'zerver/confirm_continue_registration.html', context=context) # This email address it not allowed to join this organization, so # just send the user back to the registration page. url = reverse('register') context = login_context(request) extra_context = { 'form': form, 'current_url': lambda: url, 'from_multiuse_invite': from_multiuse_invite, 'multiuse_object_key': multiuse_object_key } # type: Mapping[str, Any] context.update(extra_context) return render(request, 'zerver/accounts_home.html', context=context)
def accounts_home( request: HttpRequest, multiuse_object_key: str = "", multiuse_object: Optional[MultiuseInvite] = None, ) -> HttpResponse: try: realm = get_realm(get_subdomain(request)) except Realm.DoesNotExist: return HttpResponseRedirect(reverse(find_account)) if realm.deactivated: return redirect_to_deactivation_notice() from_multiuse_invite = False streams_to_subscribe = None invited_as = None if multiuse_object: # multiuse_object's realm should have been validated by the caller, # so this code shouldn't be reachable with a multiuse_object which # has its realm mismatching the realm of the request. assert realm == multiuse_object.realm streams_to_subscribe = multiuse_object.streams.all() from_multiuse_invite = True invited_as = multiuse_object.invited_as if request.method == "POST": form = HomepageForm(request.POST, realm=realm, from_multiuse_invite=from_multiuse_invite) if form.is_valid(): try: rate_limit_request_by_ip(request, domain="sends_email_by_ip") except RateLimited as e: assert e.secs_to_freedom is not None return render( request, "zerver/rate_limit_exceeded.html", context={"retry_after": int(e.secs_to_freedom)}, status=429, ) email = form.cleaned_data["email"] try: validate_email_not_already_in_realm(realm, email) except ValidationError: return redirect_to_email_login_url(email) activation_url = prepare_activation_url( email, request.session, realm=realm, streams=streams_to_subscribe, invited_as=invited_as, ) try: send_confirm_registration_email(email, activation_url, request=request, realm=realm) except EmailNotDeliveredException: logging.error("Error in accounts_home") return HttpResponseRedirect("/config-error/smtp") return HttpResponseRedirect( reverse("signup_send_confirm", kwargs={"email": email})) else: form = HomepageForm(realm=realm) context = login_context(request) context.update( form=form, current_url=request.get_full_path, multiuse_object_key=multiuse_object_key, from_multiuse_invite=from_multiuse_invite, ) return render(request, "zerver/accounts_home.html", context=context)
def login_page( request: HttpRequest, next: str = REQ(default="/"), **kwargs: Any, ) -> HttpResponse: if settings.SOCIAL_AUTH_SUBDOMAIN == get_subdomain(request): return social_auth_subdomain_login_page(request) # To support previewing the Zulip login pages, we have a special option # that disables the default behavior of redirecting logged-in users to the # logged-in app. is_preview = "preview" in request.GET if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: if request.user and request.user.is_verified(): return HttpResponseRedirect(request.user.realm.uri) elif request.user.is_authenticated and not is_preview: return HttpResponseRedirect(request.user.realm.uri) if is_subdomain_root_or_alias( request) and settings.ROOT_DOMAIN_LANDING_PAGE: redirect_url = reverse("realm_redirect") if request.GET: redirect_url = append_url_query_string(redirect_url, request.GET.urlencode()) return HttpResponseRedirect(redirect_url) realm = get_realm_from_request(request) if realm and realm.deactivated: return redirect_to_deactivation_notice() extra_context = kwargs.pop("extra_context", {}) extra_context["next"] = next if dev_auth_enabled() and kwargs.get( "template_name") == "zerver/development/dev_login.html": from zerver.views.development.dev_login import add_dev_login_context if "new_realm" in request.POST: try: realm = get_realm(request.POST["new_realm"]) except Realm.DoesNotExist: realm = None add_dev_login_context(realm, extra_context) if realm and "new_realm" in request.POST: # If we're switching realms, redirect to that realm, but # only if it actually exists. return HttpResponseRedirect(realm.uri) if "username" in request.POST: extra_context["email"] = request.POST["username"] extra_context.update(login_context(request)) if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: return start_two_factor_auth(request, extra_context=extra_context, **kwargs) try: template_response = DjangoLoginView.as_view( authentication_form=OurAuthenticationForm, extra_context=extra_context, **kwargs)(request) except ZulipLDAPConfigurationError as e: assert len(e.args) > 1 return redirect_to_misconfigured_ldap_notice(request, e.args[1]) if isinstance(template_response, SimpleTemplateResponse): # Only those responses that are rendered using a template have # context_data attribute. This attribute doesn't exist otherwise. It is # added in SimpleTemplateResponse class, which is a derived class of # HttpResponse. See django.template.response.SimpleTemplateResponse, # https://github.com/django/django/blob/2.0/django/template/response.py#L19 update_login_page_context(request, template_response.context_data) assert isinstance(template_response, HttpResponse) return template_response
def get_context(self, **kwargs: Any) -> Dict[str, Any]: """Get the dummy context for shallow testing. The context returned will always contain a parameter called `shallow_tested`, which tells the signal receiver that the test was not rendered in an actual logical test (so we can still do coverage reporting on which templates have a logical test). Note: `context` just holds dummy values used to make the test pass. This context only ensures that the templates do not throw a 500 error when rendered using dummy data. If new required parameters are added to a template, this test will fail; the usual fix is to just update the context below to add the new parameter to the dummy data. :param kwargs: Keyword arguments can be used to update the base context. """ user_profile = self.example_user('hamlet') realm = user_profile.realm email = user_profile.email context = dict( sidebar_index="zerver/help/include/sidebar_index.md", doc_root="/help/", article="zerver/help/index.md", shallow_tested=True, user_profile=user_profile, user=user_profile, form=DummyForm(full_name=get_form_value('John Doe'), terms=get_form_value(True), email=get_form_value(email), emails=get_form_value(email), subdomain=get_form_value("zulip"), next_param=get_form_value("billing")), current_url=lambda: 'www.zulip.com', integrations_dict={}, referrer=dict( full_name='John Doe', realm=dict(name='zulip.com'), ), message_count=0, messages=[dict(header='Header')], new_streams=dict(html=''), data=dict(title='Title'), device_info={ "device_browser": "Chrome", "device_os": "Windows", "device_ip": "127.0.0.1", "login_time": "9:33am NewYork, NewYork", }, api_uri_context={}, realm_plan_type=Realm.LIMITED, cloud_annual_price=80, seat_count=8, request=RequestFactory().get("/"), invite_as={"MEMBER": 1}, max_file_upload_size=25, avatar_urls={"*****@*****.**": "www.zulip.com"}, realm_admin_emails=lambda _: "admin emails", get_discount_for_realm=lambda _: 0, realm_icon_url=lambda _: "url", realm=realm, ) # A necessary block to make login_context available to templates. request = mock.MagicMock() request.user = AnonymousUser() request.realm = realm context.update(login_context(request)) context.update(kwargs) return context
def maybe_send_to_registration( request: HttpRequest, email: str, full_name: str = '', mobile_flow_otp: Optional[str] = None, desktop_flow_otp: Optional[str] = None, is_signup: bool = False, password_required: bool = True, multiuse_object_key: str = '', full_name_validated: bool = False) -> HttpResponse: """Given a successful authentication for an email address (i.e. we've confirmed the user controls the email address) that does not currently have a Zulip account in the target realm, send them to the registration flow or the "continue to registration" flow, depending on is_signup, whether the email address can join the organization (checked in HomepageForm), and similar details. """ # In the desktop and mobile registration flows, the sign up # happens in the browser so the user can use their # already-logged-in social accounts. Then at the end, with the # user account created, we pass the appropriate data to the app # via e.g. a `zulip://` redirect. We store the OTP keys for the # mobile/desktop flow in the session with 1-hour expiry, because # we want this configuration of having a successful authentication # result in being logged into the app to persist if the user makes # mistakes while trying to authenticate (E.g. clicks the wrong # Google account, hits back, etc.) during a given browser session, # rather than just logging into the webapp in the target browser. # # We can't use our usual pre-account-creation state storage # approach of putting something in PreregistrationUser, because # that would apply to future registration attempts on other # devices, e.g. just creating an account on the web on their laptop. assert not (mobile_flow_otp and desktop_flow_otp) if mobile_flow_otp: set_expirable_session_var(request.session, 'registration_mobile_flow_otp', mobile_flow_otp, expiry_seconds=3600) elif desktop_flow_otp: set_expirable_session_var(request.session, 'registration_desktop_flow_otp', desktop_flow_otp, expiry_seconds=3600) if multiuse_object_key: from_multiuse_invite = True multiuse_obj = Confirmation.objects.get( confirmation_key=multiuse_object_key).content_object realm = multiuse_obj.realm invited_as = multiuse_obj.invited_as else: from_multiuse_invite = False multiuse_obj = None try: realm = get_realm(get_subdomain(request)) except Realm.DoesNotExist: realm = None invited_as = PreregistrationUser.INVITE_AS['MEMBER'] form = HomepageForm({'email': email}, realm=realm, from_multiuse_invite=from_multiuse_invite) if form.is_valid(): # If the email address is allowed to sign up for an account in # this organization, construct a PreregistrationUser and # Confirmation objects, and then send the user to account # creation or confirm-continue-registration depending on # is_signup. try: prereg_user = PreregistrationUser.objects.filter( email__iexact=email, realm=realm).latest("invited_at") # password_required and full_name data passed here as argument should take precedence # over the defaults with which the existing PreregistrationUser that we've just fetched # was created. prereg_user.password_required = password_required update_fields = ["password_required"] if full_name: prereg_user.full_name = full_name prereg_user.full_name_validated = full_name_validated update_fields.extend(["full_name", "full_name_validated"]) prereg_user.save(update_fields=update_fields) except PreregistrationUser.DoesNotExist: prereg_user = create_preregistration_user( email, request, password_required=password_required, full_name=full_name, full_name_validated=full_name_validated, ) if multiuse_obj is not None: request.session.modified = True streams_to_subscribe = list(multiuse_obj.streams.all()) prereg_user.streams.set(streams_to_subscribe) prereg_user.invited_as = invited_as prereg_user.save() # We want to create a confirmation link to create an account # in the current realm, i.e. one with a hostname of # realm.host. For the Apache REMOTE_USER_SSO auth code path, # this is preferable over realm.get_host() because the latter # contains the port number of the Apache instance and we want # to send the user back to nginx. But if we're in the realm # creation code path, there might not be a realm yet, so we # have to use request.get_host(). if realm is not None: host = realm.host else: host = request.get_host() # Mark 'host' as safe for use in a redirect. It's pulled from the # current request or realm, both of which only allow a limited set of # trusted hosts. confirmation_link = create_confirmation_link( prereg_user, mark_sanitized(host), Confirmation.USER_REGISTRATION) if is_signup: return redirect(confirmation_link) context = { 'email': email, 'continue_link': confirmation_link, 'full_name': full_name } return render(request, 'zerver/confirm_continue_registration.html', context=context) # This email address it not allowed to join this organization, so # just send the user back to the registration page. url = reverse('register') context = login_context(request) extra_context: Mapping[str, Any] = { 'form': form, 'current_url': lambda: url, 'from_multiuse_invite': from_multiuse_invite, 'multiuse_object_key': multiuse_object_key, 'mobile_flow_otp': mobile_flow_otp, 'desktop_flow_otp': desktop_flow_otp, } context.update(extra_context) return render(request, 'zerver/accounts_home.html', context=context)