mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 22:43:42 +00:00
portico: Add page for redirecting to a realm subdomain.
This commit is contained in:
@@ -641,6 +641,18 @@ button.login-google-button {
|
|||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#find-account-section {
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.8em;
|
||||||
|
line-height: 1.5;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
#find-account-link {
|
||||||
|
color: hsl(164, 100%, 23%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.split-view .actions a,
|
.split-view .actions a,
|
||||||
.back-to-login {
|
.back-to-login {
|
||||||
color: hsl(164, 100%, 23%);
|
color: hsl(164, 100%, 23%);
|
||||||
|
|||||||
@@ -2178,3 +2178,33 @@ input.new-organization-button {
|
|||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#realm_redirect_subdomain {
|
||||||
|
text-align: right;
|
||||||
|
position: relative;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#realm_redirect_external_host {
|
||||||
|
font-size: 20px;
|
||||||
|
top: 13px;
|
||||||
|
left: 5px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#realm_redirect_description {
|
||||||
|
top: 15px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-redirect-form #find-account-link {
|
||||||
|
color: hsl(165, 100.0%, 14.7%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-redirect-form #find-account-section {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-redirect-form #enter-realm-button {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|||||||
43
templates/zerver/realm_redirect.html
Normal file
43
templates/zerver/realm_redirect.html
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{% extends "zerver/portico.html" %}
|
||||||
|
|
||||||
|
{% block portico_content %}
|
||||||
|
|
||||||
|
<div class="app find-account-page flex full-page">
|
||||||
|
<div class="inline-block new-style">
|
||||||
|
<div class="lead">
|
||||||
|
<h1 class="get-started">{{ _("Log in to your organization") }}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="app-main find-account-page-container white-box">
|
||||||
|
<div class="realm-redirect-form">
|
||||||
|
<form class="form-inline" name="realm_redirect_form"
|
||||||
|
action="/accounts/go/?{{ request.GET.urlencode() }}" method="post">
|
||||||
|
{{ csrf_input }}
|
||||||
|
<div class="input-box moving-label horizontal">
|
||||||
|
<div class="inline-block relative">
|
||||||
|
<p id="realm_redirect_description">{{ _("Enter your organization URL:") }}</p>
|
||||||
|
<input
|
||||||
|
type="text" value="{% if form.subdomain.value() %}{{ form.subdomain.value() }}{% endif %}"
|
||||||
|
placeholder="{{ _('your-organization-url') }}" autofocus id="realm_redirect_subdomain" name="subdomain"
|
||||||
|
autocomplete="off" required/>
|
||||||
|
<span id="realm_redirect_external_host">.{{external_host}}</span>
|
||||||
|
</div>
|
||||||
|
<div id="errors">
|
||||||
|
{% if form.subdomain.errors %}
|
||||||
|
{% for error in form.subdomain.errors %}
|
||||||
|
<div class="alert alert-error">{{ error }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<button id="enter-realm-button" type="submit">{{ _('Next') }}</button>
|
||||||
|
<p id="find-account-section">
|
||||||
|
{{ _("Can't remember your organization URL?") }}
|
||||||
|
<a target="_blank" id="find-account-link" href="/accounts/find/">{{ _("Find your account.") }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -128,6 +128,8 @@ IGNORED_PHRASES = [
|
|||||||
r"GIF",
|
r"GIF",
|
||||||
# Emoji name placeholder
|
# Emoji name placeholder
|
||||||
r"leafy green vegetable",
|
r"leafy green vegetable",
|
||||||
|
# Subdomain placeholder
|
||||||
|
r"your-organization-url",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Sort regexes in descending order of their lengths. As a result, the
|
# Sort regexes in descending order of their lengths. As a result, the
|
||||||
|
|||||||
@@ -349,3 +349,12 @@ class FindMyTeamForm(forms.Form):
|
|||||||
raise forms.ValidationError(_("Please enter at most 10 emails."))
|
raise forms.ValidationError(_("Please enter at most 10 emails."))
|
||||||
|
|
||||||
return emails
|
return emails
|
||||||
|
|
||||||
|
class RealmRedirectForm(forms.Form):
|
||||||
|
subdomain = forms.CharField(max_length=Realm.MAX_REALM_SUBDOMAIN_LENGTH, required=True)
|
||||||
|
|
||||||
|
def clean_subdomain(self) -> str:
|
||||||
|
subdomain = self.cleaned_data['subdomain']
|
||||||
|
if get_realm(subdomain) is None:
|
||||||
|
raise ValidationError(_("We couldn't find that Zulip organization."))
|
||||||
|
return subdomain
|
||||||
|
|||||||
@@ -3150,3 +3150,23 @@ class TwoFactorAuthTest(ZulipTestCase):
|
|||||||
class NameRestrictionsTest(ZulipTestCase):
|
class NameRestrictionsTest(ZulipTestCase):
|
||||||
def test_whitelisted_disposable_domains(self) -> None:
|
def test_whitelisted_disposable_domains(self) -> None:
|
||||||
self.assertFalse(is_disposable_domain('OPayQ.com'))
|
self.assertFalse(is_disposable_domain('OPayQ.com'))
|
||||||
|
|
||||||
|
class RealmRedirectTest(ZulipTestCase):
|
||||||
|
def test_realm_redirect_without_next_param(self) -> None:
|
||||||
|
result = self.client_get("/accounts/go/")
|
||||||
|
self.assert_in_success_response(["Enter your organization URL"], result)
|
||||||
|
|
||||||
|
result = self.client_post("/accounts/go/", {"subdomain": "zephyr"})
|
||||||
|
self.assertEqual(result.status_code, 302)
|
||||||
|
self.assertEqual(result["Location"], "http://zephyr.testserver")
|
||||||
|
|
||||||
|
result = self.client_post("/accounts/go/", {"subdomain": "invalid"})
|
||||||
|
self.assert_in_success_response(["We couldn't find that Zulip organization."], result)
|
||||||
|
|
||||||
|
def test_realm_redirect_with_next_param(self) -> None:
|
||||||
|
result = self.client_get("/accounts/go/?next=billing")
|
||||||
|
self.assert_in_success_response(['Enter your organization URL', 'action="/accounts/go/?next=billing"'], result)
|
||||||
|
|
||||||
|
result = self.client_post("/accounts/go/?next=billing", {"subdomain": "lear"})
|
||||||
|
self.assertEqual(result.status_code, 302)
|
||||||
|
self.assertEqual(result["Location"], "http://lear.testserver/billing")
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from django.conf import settings
|
|||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from django.template import Template, Context
|
from django.template import Template, Context
|
||||||
from django.template.loader import get_template
|
from django.template.loader import get_template
|
||||||
|
from django.test.client import RequestFactory
|
||||||
|
|
||||||
from zerver.lib.test_helpers import get_all_templates
|
from zerver.lib.test_helpers import get_all_templates
|
||||||
from zerver.lib.test_classes import (
|
from zerver.lib.test_classes import (
|
||||||
@@ -183,6 +184,8 @@ class TemplateTestCase(ZulipTestCase):
|
|||||||
terms=get_form_value(True),
|
terms=get_form_value(True),
|
||||||
email=get_form_value(email),
|
email=get_form_value(email),
|
||||||
emails=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',
|
current_url=lambda: 'www.zulip.com',
|
||||||
integrations_dict={},
|
integrations_dict={},
|
||||||
@@ -202,6 +205,7 @@ class TemplateTestCase(ZulipTestCase):
|
|||||||
api_uri_context={},
|
api_uri_context={},
|
||||||
cloud_annual_price=80,
|
cloud_annual_price=80,
|
||||||
seat_count=8,
|
seat_count=8,
|
||||||
|
request=RequestFactory().get("/")
|
||||||
)
|
)
|
||||||
|
|
||||||
context.update(kwargs)
|
context.update(kwargs)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from zerver.lib.actions import do_change_password, do_change_full_name, do_chang
|
|||||||
email_not_system_bot, validate_email_for_realm, \
|
email_not_system_bot, validate_email_for_realm, \
|
||||||
do_set_user_display_setting, lookup_default_stream_groups, bulk_add_subscriptions
|
do_set_user_display_setting, lookup_default_stream_groups, bulk_add_subscriptions
|
||||||
from zerver.forms import RegistrationForm, HomepageForm, RealmCreationForm, \
|
from zerver.forms import RegistrationForm, HomepageForm, RealmCreationForm, \
|
||||||
CreateUserForm, FindMyTeamForm
|
CreateUserForm, FindMyTeamForm, RealmRedirectForm
|
||||||
from django_auth_ldap.backend import LDAPBackend, _LDAPUser
|
from django_auth_ldap.backend import LDAPBackend, _LDAPUser
|
||||||
from zerver.decorator import require_post, has_request_variables, \
|
from zerver.decorator import require_post, has_request_variables, \
|
||||||
JsonableError, REQ, do_login
|
JsonableError, REQ, do_login
|
||||||
@@ -34,9 +34,9 @@ from zerver.lib.subdomains import get_subdomain, is_root_domain_available
|
|||||||
from zerver.lib.timezone import get_all_timezones
|
from zerver.lib.timezone import get_all_timezones
|
||||||
from zerver.lib.users import get_accounts_for_email
|
from zerver.lib.users import get_accounts_for_email
|
||||||
from zerver.lib.zephyr import compute_mit_user_fullname
|
from zerver.lib.zephyr import compute_mit_user_fullname
|
||||||
from zerver.views.auth import create_preregistration_user, \
|
from zerver.views.auth import create_preregistration_user, redirect_and_log_into_subdomain, \
|
||||||
redirect_and_log_into_subdomain, \
|
redirect_to_deactivation_notice, get_safe_redirect_to
|
||||||
redirect_to_deactivation_notice
|
|
||||||
from zproject.backends import ldap_auth_enabled, password_auth_enabled, ZulipLDAPAuthBackend, \
|
from zproject.backends import ldap_auth_enabled, password_auth_enabled, ZulipLDAPAuthBackend, \
|
||||||
ZulipLDAPException, email_auth_enabled
|
ZulipLDAPException, email_auth_enabled
|
||||||
|
|
||||||
@@ -515,3 +515,16 @@ def find_account(request: HttpRequest) -> HttpResponse:
|
|||||||
'zerver/find_account.html',
|
'zerver/find_account.html',
|
||||||
context={'form': form, 'current_url': lambda: url,
|
context={'form': form, 'current_url': lambda: url,
|
||||||
'emails': emails},)
|
'emails': emails},)
|
||||||
|
|
||||||
|
def realm_redirect(request: HttpRequest) -> HttpResponse:
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = RealmRedirectForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
subdomain = form.cleaned_data['subdomain']
|
||||||
|
realm = get_realm(subdomain)
|
||||||
|
redirect_to = get_safe_redirect_to(request.GET.get("next", ""), realm.uri)
|
||||||
|
return HttpResponseRedirect(redirect_to)
|
||||||
|
else:
|
||||||
|
form = RealmRedirectForm()
|
||||||
|
|
||||||
|
return render(request, 'zerver/realm_redirect.html', context={'form': form})
|
||||||
|
|||||||
@@ -452,6 +452,10 @@ i18n_urls = [
|
|||||||
url(r'^accounts/find/$', zerver.views.registration.find_account,
|
url(r'^accounts/find/$', zerver.views.registration.find_account,
|
||||||
name='zerver.views.registration.find_account'),
|
name='zerver.views.registration.find_account'),
|
||||||
|
|
||||||
|
# Go to organization subdomain
|
||||||
|
url(r'^accounts/go/$', zerver.views.registration.realm_redirect,
|
||||||
|
name='zerver.views.registration.realm_redirect'),
|
||||||
|
|
||||||
# Realm Creation
|
# Realm Creation
|
||||||
url(r'^new/$', zerver.views.registration.create_realm,
|
url(r'^new/$', zerver.views.registration.create_realm,
|
||||||
name='zerver.views.create_realm'),
|
name='zerver.views.create_realm'),
|
||||||
|
|||||||
Reference in New Issue
Block a user