snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:05:30 +05:00
commit 64898b2c79
8999 changed files with 1757358 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
{% extends "zerver/portico_signup.html" %}
{# Home page for not logged-in users. #}
{% block title %}
<title>{{ _("Sign up") }} | Zulip</title>
{% endblock %}
{# This is where we pitch the app and solicit signups. #}
{% block portico_content %}
<!-- The following empty tag has unique data-page-id so that this
page can be easily identified in it's respective JavaScript file -->
<div data-page-id="accounts-home"></div>
<div class="app register-page split-view flex full-page new-style">
<div class="inline-block">
<div class="lead">
<h1 class="get-started">{{ _("Sign up for Zulip") }}</h1>
</div>
<div class="app-main register-page-container white-box {% if realm_invite_required and not from_multiuse_invite %}closed-realm{% endif %}">
<div class="register-form new-style">
{% if realm_name %}
<div class="left-side">
<div class="org-header">
<img class="avatar" src="{{ realm_icon }}" alt="" />
<div class="info-box">
<div class="organization-name">{{ realm_name }}</div>
<div class="organization-path">{{ realm_url }}</div>
</div>
</div>
<div class="description">
{{ realm_description|safe }}
</div>
<div class="invite-required">
<hr />
<i class="fa fa-lock"></i>{{ _("You need an invitation to join this organization.") }}
</div>
</div>
{% endif %}
<div class="right-side">
{% if no_auth_enabled %}
<div class="alert">
<p>No authentication backends are enabled on this
server yet, so it is impossible to register!</p>
<p>
See
the <a href="https://zulip.readthedocs.io/en/latest/production/install.html#step-3-configure-zulip">Zulip
authentication documentation</a> to learn how to
configure authentication backends.
</p>
</div>
{% else %}
{% if password_auth_enabled %}
<form class="form-inline" id="send_confirm" name="email_form"
action="{{ current_url() }}" method="post">
{{ csrf_input }}
<div class="input-box no-validate">
<input type="email" id="email" class="email" name="email" value="" autofocus required />
<label for="email">{{ _('Email') }}</label>
<div class="alert alert-error email-frontend-error"></div>
{% if form.email.errors %}
{% for error in form.email.errors %}
<div class="email-backend-error alert alert-error">{{ error }}</div>
{% endfor %}
{% endif %}
</div>
<button class="full-width" type="submit">{{ _('Sign up') }}</button>
</form>
{% if external_authentication_methods|length > 0 %}
<div class="or"><span>{{ _('OR') }}</span></div>
{% endif %}
{% endif %}
{% for backend in external_authentication_methods %}
<div class="login-social">
<form class="form-inline" action="{{ backend.signup_url }}" method="get">
{% if next %}
<input type="hidden" name="next" value="{{ next }}" />
{% endif %}
<input type='hidden' name='multiuse_object_key' value='{{ multiuse_object_key }}' />
<button id="register_auth_button_{{ backend.name }}" class="login-social-button full-width"
{% if backend.display_icon %} style="background-image:url({{ backend.display_icon }})" {% endif %}>
{{ _('Sign up with %(identity_provider)s', identity_provider=backend.display_name) }}
</button>
</form>
</div>
{% endfor %}
<div class="register-form-login-redirect actions">
{{ _('Already have an account?') }}<a class="register-link" href="/login/"> {{ _('Log in') }}</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,37 @@
<div class="micromodal" id="change-email-address-visibility-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1">
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="change-email-address-visibility-modal-label">
<header class="modal__header">
<div class="modal__header-content">
<h1 id="change-email-address-visibility-modal-label" class="modal__title dialog_heading">
{{ _('Configure email address privacy') }}
</h1>
</div>
<button type="button" class="modal__close" aria-label="{{ _('Close modal') }}" tabindex="0" data-micromodal-close>
<i class="zulip-icon zulip-icon-close" aria-hidden="true"></i>
</button>
</header>
<main class="modal__content">
<p>
{{ _('Zulip lets you control which roles in the organization can view your email address.') }}
{{ _('Do you want to change the privacy setting for your email from the default configuration for this organization?') }}
</p>
<label for="new_user_email_address_visibility">{{ _('Who can access your email address') }}</label>
<select id="new_user_email_address_visibility" class="modal_select">
{% for value, name in email_address_visibility_options_dict.items() %}
<option value="{{ value }}" {% if value == default_email_address_visibility %}selected{% endif %}>{{name}}</option>
{% endfor %}
</select>
<p>
{% trans %}You can also change this setting <a href="{{ root_domain_url }}/help/configure-email-visibility" target="_blank" rel="noopener noreferrer">after you join</a>.{% endtrans %}
</p>
</main>
<footer class="modal__footer">
<button class="modal__button dialog_exit_button" aria-label="{{ '(Close this dialog window)' }}" data-micromodal-close>{{ _('Cancel') }}</button>
<button class="modal__button dialog_submit_button">
<span>{{ _('Confirm') }}</span>
</button>
</footer>
</div>
</div>
</div>

View File

@@ -0,0 +1,19 @@
<p id="new-user-email-address-visibility" class="registration-form-hint">
<input type="hidden" name="email_address_visibility" value="{{ default_email_address_visibility }}" id="email_address_visibility"/>
<span class="current-selected-option">
{% if default_email_address_visibility == email_address_visibility_admins_only %}
{% trans %}Administrators of this Zulip organization will be able to see this email address.
{% endtrans %}
{% elif default_email_address_visibility == email_address_visibility_moderators %}
{% trans %}Administrators and moderators of this Zulip organization will be able to see this email address.
{% endtrans %}
{% elif default_email_address_visibility == email_address_visibility_nobody %}
{% trans %}Nobody in this Zulip organization will be able to see this email address.
{% endtrans %}
{% else %}
{% trans %}Other users in this Zulip organization will be able to see this email address.
{% endtrans %}
{% endif %}
</span>
<a target="_blank" class="change_email_address_visibility" rel="noopener noreferrer">{{ _('Change') }}</a>
</p>

View File

@@ -0,0 +1,239 @@
{% extends "zerver/portico_signup.html" %}
{% set entrypoint = "register" %}
{% block title %}
<title>{{ _("Registration") }} | Zulip</title>
{% endblock %}
{#
Gather other user information, after having confirmed
their email address.
Form is validated both client-side using jquery-validation (see signup.js) and server-side.
#}
{% block portico_content %}
<div class="register-account flex full-page">
<div class="center-block new-style" id="create-account">
<div class="pitch">
{% if creating_new_realm %}
<h1>{{ _('Create your organization') }}</h1>
{% else %}
<h1>{{ _('Create your account') }}</h1>
{% endif %}
{% trans %}
<p>Enter your account details to complete registration.</p>
{% endtrans %}
</div>
<form method="post" class="white-box" id="registration" action="{{ url('accounts_register') }}">
{{ csrf_input }}
<fieldset class="org-registration">
{% if creating_new_realm %}
<legend>{{ _('Your organization') }}
{% if not form.realm_subdomain.errors %}
<span class="edit-realm-details" role="button" tabindex="0"><i class="fa fa-pencil"></i></span>
{% endif %}
</legend>
{% with %}
{% set user_registration_form = "true" %}
{% include 'zerver/create_realm/realm_creation_name_form_field.html' %}
{% include 'zerver/create_realm/realm_creation_base_form_fields.html' %}
{% include 'zerver/create_realm/realm_creation_subdomain_form_field.html' %}
{% if is_realm_import_enabled %}
{% include 'zerver/create_realm/realm_creation_import_form_field.html' %}
{% endif %}
{% endwith %}
{% if not form.realm_subdomain.errors %}
<div class="not-editable-realm-details">
<div class="input-box">
<label for="id_realm_name" class="inline-block label-title">{{ _('Organization name') }}</label>
<div id="id_realm_name" class="not-editable-realm-field">{{ form.realm_name.value() }}</div>
</div>
<div class="input-box">
<label for="id_realm_type" class="inline-block label-title">{{ _('Organization type') }}</label>
<div id="id_realm_type" class="not-editable-realm-field">{{ selected_realm_type_name }}</div>
</div>
<div class="input-box">
<label for="id_realm_default_language" class="inline-block label-title">{{ _('Organization language') }}</label>
<div id="id_realm_default_language" class="not-editable-realm-field">{{ selected_realm_default_language_name }}</div>
</div>
<div class="input-box">
<label for="id_realm_subdomain" class="inline-block label-title">{{ _('Organization URL') }}</label>
<div id="id_realm_subdomain" class="not-editable-realm-field">{% if form.realm_subdomain.value() %}{{ form.realm_subdomain.value() }}.{% endif %}{{external_host}}</div>
</div>
</div>
{% endif %}
{% endif %}
</fieldset>
<fieldset class="user-registration">
{% if creating_new_realm %}
<legend>{{ _('Your account') }}</legend>
{% endif %}
{% if realm_name and not creating_new_realm %}
<img class="avatar inline-block" src="{{ realm_icon }}" alt="" />
<div class="info-box inline-block">
<div class="organization-name organization-name-delayed-tooltip">{{ realm_name }}</div>
<div class="organization-path">{{ realm_url }}</div>
</div>
{% endif %}
<div class="input-box">
<input type='hidden' name='key' value='{{ key }}' />
<input type='hidden' name='timezone' id='timezone'/>
<label for="id_email" class="inline-block label-title">{{ _('Email') }}</label>
<div id="id_email">{{ email }}</div>
{% if not creating_new_realm %}
{% include 'zerver/create_user/new_user_email_address_visibility.html' %}
{% endif %}
</div>
{% if accounts %}
<div class="input-box">
<div class="inline-block relative">
<select class="select" name="source_realm_id" id="source_realm_select">
<option value=""
{% if "source_realm_id" in form.data and form.data["source_realm_id"] == "" %}selected {% endif %}>
{{ _('Don&rsquo;t import settings') }}
</option>
{% for account in accounts %}
<option value="{{ account.realm_id }}" data-full-name="{{account.full_name}}" data-avatar="{{account.avatar}}"
{% if ("source_realm_id" in form.data and account.realm_id == form.data["source_realm_id"]|int)
or ("source_realm_id" not in form.data and loop.index0 == 0) %} selected {% endif %}>
{{ account.realm_name }}
</option>
{% endfor %}
</select>
</div>
<label for="source_realm_id" class="inline-block">{{ _('Import settings from existing Zulip account') }}
<a href="{{ root_domain_url }}/help/import-your-settings"><i class="fa fa-question-circle"></i></a>
</label>
</div>
{% endif %}
<div class="input-box" id="full_name_input_section">
{% if lock_name %}
<p class="fakecontrol">{{ full_name }}</p>
{% else %}
<input id="id_full_name" class="required" type="text" name="full_name"
value="{% if full_name %}{{ full_name }}{% elif form.full_name.value() %}{{ form.full_name.value() }}{% endif %}"
maxlength="{{ MAX_NAME_LENGTH }}" placeholder="{% trans %}Your full name{% endtrans %}" required />
<label for="id_full_name" class="inline-block label-title">{{ _('Name') }}</label>
{% if form.full_name.errors %}
{% for error in form.full_name.errors %}
<p class="help-inline text-error">{{ error }}</p>
{% endfor %}
{% endif %}
{% endif %}
<p class="registration-form-hint">{{ _('This is how your account is displayed in Zulip.') }}</p>
</div>
<div class="input-box" id="profile_info_section" style="display:none;">
<img id="profile_avatar" />
<div id="profile_full_name"></div>
</div>
{% if require_ldap_password %}
<div class="input-box password-div">
<input id="ldap-password" class="required" type="password" name="password" autocomplete="off" required />
<label for="ldap-password" class="inline-block">{{ _('Password') }}</label>
<i class="zulip-icon zulip-icon-hide password_visibility_toggle" role="button" tabindex="0"></i>
<span class="help-inline">
{{ _('Enter your LDAP/Active Directory password.') }}
</span>
</div>
{% elif password_required %}
<div class="input-box password-div">
<input id="id_password" class="required" type="password" name="password" autocomplete="new-password"
value="{% if form.password.value() %}{{ form.password.value() }}{% endif %}"
data-min-length="{{password_min_length}}"
data-max-length="{{ password_max_length }}"
data-min-guesses="{{password_min_guesses}}" required />
<label for="id_password" class="inline-block">{{ _('Password') }}</label>
<i class="zulip-icon zulip-icon-hide password_visibility_toggle" role="button" tabindex="0"></i>
{% if full_name %}
<span class="help-inline">
{{ _('This is used for mobile applications and other tools that require a password.') }}
</span>
{% endif %}
{% if form.password.errors %}
{% for error in form.password.errors %}
<p class="help-inline text-error">{{ error }}</p>
{% endfor %}
{% endif %}
<div class="progress" id="pw_strength" title="{{ _('Password strength') }}">
<div class="bar bar-danger" style="width: 10%;"></div>
</div>
</div>
{% endif %}
</fieldset>
{% if default_stream_groups %}
<hr />
<div class="default-stream-groups">
<p>{{ _('What are you interested in?') }}</p>
{% for default_stream_group in default_stream_groups %}
<div class="input-group">
<label for="id_default_stream_group__{{ default_stream_group.id }}"
class="inline-block checkbox">
<input class="inline-block" type="checkbox"
name="default_stream_group"
id="id_default_stream_group__{{ default_stream_group.id }}" value="{{ default_stream_group.name }}"
{% if "default_stream_group" in form.data and default_stream_group.id in form.data.getlist('default_stream_group') %} checked {% endif %} />
<span class="rendered-checkbox"></span>
{% set comma = joiner(", ") %}
<span class="default_stream_group_name inline-block"
title="{{ default_stream_group.description }}">
{{ default_stream_group.name }}
</span>
(
{%- for stream in default_stream_group.streams.all() -%}
{{- comma() -}} <span class="stream_name inline-block">#{{ stream.name }}</span>
{%- endfor -%}
)
</label>
</div>
{% endfor %}
</div>
<hr />
{% endif %}
{% if creating_new_realm %}
{% include 'zerver/create_realm/found_zulip_form_field.html' %}
{% endif %}
<div class="input-group">
{% if terms_of_service %}
{% include 'zerver/create_user/terms_of_service_form_field.html' %}
{% endif %}
{% if corporate_enabled %}
<div class="input-group marketing-emails">
<label for="id_enable_marketing_emails" class="inline-block checkbox marketing_emails_checkbox">
<input id="id_enable_marketing_emails" type="checkbox" name="enable_marketing_emails"
checked="checked" />
<span class="rendered-checkbox"></span>
{% trans %}Subscribe me to Zulip's low-traffic newsletter (a few emails a year).{% endtrans %}
</label>
</div>
{% endif %}
<div class="register-button-box">
<button class="register-button" type="submit">
<span>{{ _('Sign up') }}</span>
<object class="loader" type="image/svg+xml" data="{{ static('images/loading/loader-white.svg') }}"></object>
</button>
<input type="hidden" name="next" value="{{ next }}" />
</div>
</div>
</form>
</div>
</div>
{% if not creating_new_realm %}
{% include 'zerver/create_user/change_email_address_visibility_modal.html' %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,21 @@
<div class="input-group terms-of-service">
{#
This is somewhat subtle.
Checkboxes have a name and value, and when the checkbox is ticked, the form posts
with name=value. If the checkbox is unticked, the field just isn't present at all.
This is distinct from 'checked', which determines whether the checkbox appears
at all. (So, it's not symmetric to the code above.)
#}
<label for="id_terms" class="inline-block checkbox">
<input id="id_terms" class="required" type="checkbox" name="terms"
{% if form.terms.value() %}checked="checked"{% endif %} />
<span class="rendered-checkbox"></span>
{% trans %}I agree to the <a href="{{ root_domain_url }}/policies/terms" target="_blank" rel="noopener noreferrer">Terms of Service</a>.{% endtrans %}
</label>
{% if form.terms.errors %}
{% for error in form.terms.errors %}
<p class="error help-inline alert alert-error">{{ error }}</p>
{% endfor %}
{% endif %}
</div>