mirror of https://github.com/zulip/zulip.git
config_error: Split error pages into their own pages.
This is much easier to maintain than a giant set of if statements.
This commit is contained in:
parent
5506dffa36
commit
a21971ceae
|
@ -1,28 +0,0 @@
|
|||
<p>
|
||||
You are attempting to use the <strong>Apple auth backend</strong>, but it is
|
||||
not properly configured. To configure, please check the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
You have registered
|
||||
<code>{{ root_domain_url }}/complete/apple/</code> as the callback URL
|
||||
for your Services ID in Apple’s developer console. You can enable “Sign
|
||||
in with Apple” for an app at
|
||||
<a href="https://developer.apple.com/account/resources/">Certificates,
|
||||
Identifiers & Profiles</a>.
|
||||
</li>
|
||||
<li>
|
||||
You have set <code>SOCIAL_AUTH_APPLE_SERVICES_ID</code>,
|
||||
<code>SOCIAL_AUTH_APPLE_APP_ID</code>,
|
||||
<code>SOCIAL_AUTH_APPLE_TEAM</code>, and
|
||||
<code>SOCIAL_AUTH_APPLE_KEY</code> in
|
||||
<code>{{ settings_path }}</code>
|
||||
and stored the private key provided by Apple at
|
||||
<code>/etc/zulip/apple-auth-key.p8</code> on the Zulip server, with
|
||||
proper permissions set.
|
||||
</li>
|
||||
<li>
|
||||
Navigate back to the login page and attempt the “Sign in with Apple”
|
||||
flow again.
|
||||
</li>
|
||||
</ul>
|
|
@ -1,19 +0,0 @@
|
|||
<p>
|
||||
You attempted to use the <code>DevAuthBackend</code> authentication method,
|
||||
which is used for logging in without a password in the Zulip development
|
||||
environment.
|
||||
</p>
|
||||
<p>This backend is not available for this realm, either because:</p>
|
||||
<ul>
|
||||
<li>This Zulip server is configured as a production server.</li>
|
||||
<li>
|
||||
<code>DevAuthBackend</code> is disabled in
|
||||
<code>AUTHENTICATION_BACKENDS</code> in
|
||||
<code>{{ settings_path }}</code>.
|
||||
</li>
|
||||
<li>
|
||||
You disabled this authentication backend in
|
||||
<a href="/help/configure-authentication-methods">this realm’s
|
||||
authentication settings</a>.
|
||||
</li>
|
||||
</ul>
|
|
@ -1,23 +0,0 @@
|
|||
<p>
|
||||
You are attempting to use the <strong>GitHub auth backend</strong>, but it
|
||||
is not properly configured. To configure, please check the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
You have added
|
||||
<code>{{ root_domain_url }}/complete/github/</code> as the callback URL
|
||||
in the OAuth application in GitHub. You can create OAuth apps from
|
||||
<a href="https://github.com/settings/developers">GitHub’s developer
|
||||
site</a>.
|
||||
</li>
|
||||
<li>
|
||||
You have set <code>{{ client_id_key_name }}</code> in
|
||||
<code>{{ settings_path }}</code> and
|
||||
<code>social_auth_github_secret</code> in
|
||||
<code>{{ secrets_path }}</code> with the values from your OAuth
|
||||
application.
|
||||
</li>
|
||||
<li>
|
||||
Navigate back to the login page and attempt the GitHub auth flow again.
|
||||
</li>
|
||||
</ul>
|
|
@ -1,23 +0,0 @@
|
|||
<p>
|
||||
You are attempting to use the <strong>GitLab auth backend</strong>, but it
|
||||
is not properly configured. To configure, please check the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
You have added
|
||||
<code>{{ root_domain_url }}/complete/gitlab/</code> as the callback URL
|
||||
in the OAuth application in GitLab. You can register OAuth apps at
|
||||
<a href="https://gitlab.com/profile/applications">GitLab
|
||||
applications</a>.
|
||||
</li>
|
||||
<li>
|
||||
You have set <code>{{ client_id_key_name }}</code> in
|
||||
<code>{{ settings_path }}</code> and
|
||||
<code>social_auth_gitlab_secret</code> in
|
||||
<code>{{ secrets_path }}</code> with the values from your OAuth
|
||||
application.
|
||||
</li>
|
||||
<li>
|
||||
Navigate back to the login page and attempt the GitLab auth flow again.
|
||||
</li>
|
||||
</ul>
|
|
@ -1,26 +0,0 @@
|
|||
<p>
|
||||
You are attempting to use the <strong>Google auth backend</strong>, but it
|
||||
is not properly configured. To configure, please check the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
You have created a Google OAuth2 client and enabled the Identity Toolkit
|
||||
API. You can create OAuth2 apps at
|
||||
<a href="https://console.developers.google.com">the Google developer
|
||||
console</a>.
|
||||
</li>
|
||||
<li>
|
||||
You have configured your OAuth2 client to allow redirects to your
|
||||
server’s Google auth URL:
|
||||
<code>{{ root_domain_url }}/complete/google/</code>.
|
||||
</li>
|
||||
<li>
|
||||
You have set <code>{{ client_id_key_name }}</code> in
|
||||
<code>{{ settings_path }}</code> and
|
||||
<code>social_auth_google_secret</code> in
|
||||
<code>{{ secrets_path }}</code>.
|
||||
</li>
|
||||
<li>
|
||||
Navigate back to the login page and attempt the Google auth flow again.
|
||||
</li>
|
||||
</ul>
|
|
@ -1,121 +0,0 @@
|
|||
{% extends "zerver/portico.html" %}
|
||||
|
||||
{% block title %}
|
||||
<title>{{ _("Configuration error") }} | Zulip</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
||||
<div class="error_page" style="padding-bottom: 60px;">
|
||||
<div class="container">
|
||||
<div class="row-fluid">
|
||||
<img src="{{ static('images/errors/500art.svg') }}" alt=""/>
|
||||
<div class="errorbox config-error">
|
||||
<div class="errorcontent">
|
||||
<h1 class="lead">{{ _("Configuration error") }}</h1>
|
||||
<br />
|
||||
{% if error_name == "ldap" %}
|
||||
{% trans %}
|
||||
You are trying to log in using LDAP without creating an
|
||||
organization first. Please use EmailAuthBackend to create
|
||||
your organization and then try again.
|
||||
{% endtrans %}
|
||||
{% endif %}
|
||||
|
||||
{% if error_name == "smtp" %}
|
||||
<p>
|
||||
It appears there are problems with the
|
||||
email configuration.
|
||||
</p>
|
||||
{% if not development_environment %}
|
||||
<p>
|
||||
See <code>/var/log/zulip/errors.log</code> for more
|
||||
details on the error.
|
||||
</p>
|
||||
<p>
|
||||
You may also want to test your email configuration,
|
||||
as described in the
|
||||
<a href="https://zulip.readthedocs.io/en/latest/production/email.html">Production installation docs</a>.
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
Please have a look at our
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://zulip.readthedocs.io/en/latest/subsystems/email.html#development-and-testing"> setup guide</a>
|
||||
for forwarding emails sent in development
|
||||
environment to an email account.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if error_name == "dev_not_supported" %}
|
||||
{% include "zerver/authentication_backends/dev-not-supported-error.html" %}
|
||||
{% endif %}
|
||||
|
||||
{% if has_error_template %}
|
||||
{% if development_environment %}
|
||||
{% with %}
|
||||
{% set settings_path = secrets_path %}
|
||||
{% set client_id_key_name = "social_auth_" + error_name + "_key" %}
|
||||
{% include "zerver/authentication_backends/" + error_name + "-error.html" %}
|
||||
{% endwith %}
|
||||
<p>
|
||||
For more information, have a look at
|
||||
the <a href="https://zulip.readthedocs.io/en/latest/development/authentication.html#{{ social_backend_name }}">authentication
|
||||
setup guide</a> for the development environment.
|
||||
</p>
|
||||
{% else %}
|
||||
{% with %}
|
||||
{% set client_id_key_name = "SOCIAL_AUTH_" + error_name.upper() + "_KEY" %}
|
||||
{% include "zerver/authentication_backends/" + error_name + "-error.html" %}
|
||||
{% endwith %}
|
||||
<p>
|
||||
For more information, have a look at
|
||||
our <a href="https://zulip.readthedocs.io/en/latest/production/authentication-methods.html">authentication
|
||||
setup guide</a> and the comments in <code>{{ settings_comments_path }}</code>.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if error_name == "saml" %}
|
||||
<p>
|
||||
SAML authentication is either not enabled or misconfigured. Have a look at
|
||||
our <a href="https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#SAML">setup guide</a>.
|
||||
</p>
|
||||
{% if development_environment %}
|
||||
<p>
|
||||
See also the
|
||||
<a href="https://zulip.readthedocs.io/en/latest/development/authentication.html#saml">SAML guide</a>
|
||||
for the development environment.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if error_name == "remote_user_backend_disabled" %}
|
||||
<p>
|
||||
Authentication via the REMOTE_USER header is
|
||||
disabled in `/etc/zulip/settings.py`.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if error_name == "remote_user_header_missing" %}
|
||||
<p>
|
||||
The REMOTE_USER header is not set.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if error_name == "oidc" %}
|
||||
{# TODO: Improve the config error page for OIDC #}
|
||||
<p>
|
||||
The OpenID Connect backend is not configured correctly.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<p>After making your changes, remember to restart
|
||||
the Zulip server.</p>
|
||||
<p><a href=""> Refresh</a> to try again or <a href="/login/">click here</a> to go back to the login page.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,33 @@
|
|||
{% extends "zerver/config_error/social-container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
You are attempting to use the <strong>Apple auth backend</strong>, but it is
|
||||
not properly configured. To configure, please check the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
You have registered
|
||||
<code>{{ root_domain_url }}/complete/apple/</code> as the callback URL
|
||||
for your Services ID in Apple’s developer console. You can enable “Sign
|
||||
in with Apple” for an app at
|
||||
<a href="https://developer.apple.com/account/resources/">Certificates,
|
||||
Identifiers & Profiles</a>.
|
||||
</li>
|
||||
<li>
|
||||
You have set <code>SOCIAL_AUTH_APPLE_SERVICES_ID</code>,
|
||||
<code>SOCIAL_AUTH_APPLE_APP_ID</code>,
|
||||
<code>SOCIAL_AUTH_APPLE_TEAM</code>, and
|
||||
<code>SOCIAL_AUTH_APPLE_KEY</code> in
|
||||
<code>{{ auth_settings_path }}</code>
|
||||
and stored the private key provided by Apple at
|
||||
<code>/etc/zulip/apple-auth-key.p8</code> on the Zulip server, with
|
||||
proper permissions set.
|
||||
</li>
|
||||
<li>
|
||||
Navigate back to the login page and attempt the “Sign in with Apple”
|
||||
flow again.
|
||||
</li>
|
||||
</ul>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
|
@ -0,0 +1,28 @@
|
|||
{% extends "zerver/portico.html" %}
|
||||
|
||||
{% block title %}
|
||||
<title>{{ _("Configuration error") }} | Zulip</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
<div class="error_page" style="padding-bottom: 60px;">
|
||||
<div class="container">
|
||||
<div class="row-fluid">
|
||||
<img src="{{ static('images/errors/500art.svg') }}" alt=""/>
|
||||
<div class="errorbox config-error">
|
||||
<div class="errorcontent">
|
||||
<h1 class="lead">{{ _("Configuration error") }}</h1>
|
||||
<br />
|
||||
{% block error_content %}
|
||||
{% endblock %}
|
||||
|
||||
<p>After making your changes, remember to restart
|
||||
the Zulip server.</p>
|
||||
<p><a href=""> Refresh</a> to try again or <a href="/login/">click here</a> to go back to the login page.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,23 @@
|
|||
{% extends "zerver/config_error/container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
You attempted to use the <code>DevAuthBackend</code> authentication method,
|
||||
which is used for logging in without a password in the Zulip development
|
||||
environment.
|
||||
</p>
|
||||
<p>This backend is not available for this realm, either because:</p>
|
||||
<ul>
|
||||
<li>This Zulip server is configured as a production server.</li>
|
||||
<li>
|
||||
<code>DevAuthBackend</code> is disabled in
|
||||
<code>AUTHENTICATION_BACKENDS</code> in
|
||||
<code>{{ auth_settings_path }}</code>.
|
||||
</li>
|
||||
<li>
|
||||
You disabled this authentication backend in
|
||||
<a href="/help/configure-authentication-methods">this realm’s
|
||||
authentication settings</a>.
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
|
@ -0,0 +1,28 @@
|
|||
{% extends "zerver/config_error/social-container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
You are attempting to use the <strong>GitHub auth backend</strong>, but it
|
||||
is not properly configured. To configure, please check the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
You have added
|
||||
<code>{{ root_domain_url }}/complete/github/</code> as the callback URL
|
||||
in the OAuth application in GitHub. You can create OAuth apps from
|
||||
<a href="https://github.com/settings/developers">GitHub’s developer
|
||||
site</a>.
|
||||
</li>
|
||||
<li>
|
||||
You have set <code>{{ client_id_key_name }}</code> in
|
||||
<code>{{ auth_settings_path }}</code> and
|
||||
<code>social_auth_github_secret</code> in
|
||||
<code>{{ secrets_path }}</code> with the values from your OAuth
|
||||
application.
|
||||
</li>
|
||||
<li>
|
||||
Navigate back to the login page and attempt the GitHub auth flow again.
|
||||
</li>
|
||||
</ul>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
|
@ -0,0 +1,28 @@
|
|||
{% extends "zerver/config_error/social-container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
You are attempting to use the <strong>GitLab auth backend</strong>, but it
|
||||
is not properly configured. To configure, please check the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
You have added
|
||||
<code>{{ root_domain_url }}/complete/gitlab/</code> as the callback URL
|
||||
in the OAuth application in GitLab. You can register OAuth apps at
|
||||
<a href="https://gitlab.com/profile/applications">GitLab
|
||||
applications</a>.
|
||||
</li>
|
||||
<li>
|
||||
You have set <code>{{ client_id_key_name }}</code> in
|
||||
<code>{{ auth_settings_path }}</code> and
|
||||
<code>social_auth_gitlab_secret</code> in
|
||||
<code>{{ secrets_path }}</code> with the values from your OAuth
|
||||
application.
|
||||
</li>
|
||||
<li>
|
||||
Navigate back to the login page and attempt the GitLab auth flow again.
|
||||
</li>
|
||||
</ul>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "zerver/config_error/social-container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
You are attempting to use the <strong>Google auth backend</strong>, but it
|
||||
is not properly configured. To configure, please check the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
You have created a Google OAuth2 client and enabled the Identity Toolkit
|
||||
API. You can create OAuth2 apps at
|
||||
<a href="https://console.developers.google.com">the Google developer
|
||||
console</a>.
|
||||
</li>
|
||||
<li>
|
||||
You have configured your OAuth2 client to allow redirects to your
|
||||
server’s Google auth URL:
|
||||
<code>{{ root_domain_url }}/complete/google/</code>.
|
||||
</li>
|
||||
<li>
|
||||
You have set <code>{{ client_id_key_name }}</code> in
|
||||
<code>{{ auth_settings_path }}</code> and
|
||||
<code>social_auth_google_secret</code> in
|
||||
<code>{{ secrets_path }}</code>.
|
||||
</li>
|
||||
<li>
|
||||
Navigate back to the login page and attempt the Google auth flow again.
|
||||
</li>
|
||||
</ul>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "zerver/config_error/container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
{% trans %}
|
||||
You are trying to log in using LDAP without creating an
|
||||
organization first. Please use EmailAuthBackend to create
|
||||
your organization and then try again.
|
||||
{% endtrans %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,8 @@
|
|||
{% extends "zerver/config_error/container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
{# TODO: Improve the config error page for OIDC #}
|
||||
<p>
|
||||
The OpenID Connect backend is not configured correctly.
|
||||
</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,8 @@
|
|||
{% extends "zerver/config_error/container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
Authentication via the REMOTE_USER header is
|
||||
disabled in `/etc/zulip/settings.py`.
|
||||
</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,7 @@
|
|||
{% extends "zerver/config_error/container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
The REMOTE_USER header is not set.
|
||||
</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "zerver/config_error/container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
SAML authentication is either not enabled or misconfigured. Have a look at
|
||||
our <a href="https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#SAML">setup guide</a>.
|
||||
</p>
|
||||
{% if development_environment %}
|
||||
<p>
|
||||
See also the
|
||||
<a href="https://zulip.readthedocs.io/en/latest/development/authentication.html#saml">SAML guide</a>
|
||||
for the development environment.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,26 @@
|
|||
{% extends "zerver/config_error/container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<p>
|
||||
It appears there are problems with the
|
||||
email configuration.
|
||||
</p>
|
||||
{% if not development_environment %}
|
||||
<p>
|
||||
See <code>/var/log/zulip/errors.log</code> for more
|
||||
details on the error.
|
||||
</p>
|
||||
<p>
|
||||
You may also want to test your email configuration,
|
||||
as described in the
|
||||
<a href="https://zulip.readthedocs.io/en/latest/production/email.html">Production installation docs</a>.
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
Please have a look at our
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://zulip.readthedocs.io/en/latest/subsystems/email.html#development-and-testing"> setup guide</a>
|
||||
for forwarding emails sent in development
|
||||
environment to an email account.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "zerver/config_error/container.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
{% if development %}
|
||||
<p>
|
||||
For more information, have a look at the
|
||||
<a href="https://zulip.readthedocs.io/en/latest/development/authentication.html#{{ social_backend_name }}">authentication setup guide</a>
|
||||
for the development environment.
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
For more information, have a look at our
|
||||
<a href="https://zulip.readthedocs.io/en/latest/production/authentication-methods.html">authentication setup guide</a>
|
||||
and the comments in <code>{{ settings_comments_path }}</code>.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -697,7 +697,7 @@ html_rules: List["Rule"] = [
|
|||
"web/templates/popovers/user_card/user_card_popover_avatar.hbs",
|
||||
"web/templates/confirm_dialog/confirm_subscription_invites_warning.hbs",
|
||||
"templates/zerver/reset_confirm.html",
|
||||
"templates/zerver/config_error.html",
|
||||
"templates/zerver/config_error/container.html",
|
||||
"templates/zerver/dev_env_email_access_details.html",
|
||||
"templates/zerver/confirm_continue_registration.html",
|
||||
"templates/zerver/register.html",
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
from typing import Dict
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import render
|
||||
|
||||
|
||||
def config_error(request: HttpRequest, error_category_name: str) -> HttpResponse:
|
||||
contexts: Dict[str, Dict[str, object]] = {
|
||||
"apple": {"social_backend_name": "apple", "has_error_template": True},
|
||||
"google": {"social_backend_name": "google", "has_error_template": True},
|
||||
"github": {"social_backend_name": "github", "has_error_template": True},
|
||||
"gitlab": {"social_backend_name": "gitlab", "has_error_template": True},
|
||||
def config_error(request: HttpRequest, error_name: str) -> HttpResponse:
|
||||
assert "/" not in error_name
|
||||
context = {
|
||||
"error_name": error_name,
|
||||
}
|
||||
if settings.DEVELOPMENT:
|
||||
context["auth_settings_path"] = "zproject/dev-secrets.conf"
|
||||
context["client_id_key_name"] = f"social_auth_{error_name}_key"
|
||||
else:
|
||||
context["auth_settings_path"] = "/etc/zulip/settings.py"
|
||||
context["client_id_key_name"] = f"SOCIAL_AUTH_{error_name.upper()}_KEY"
|
||||
|
||||
context = contexts.get(error_category_name, {})
|
||||
context["error_name"] = error_category_name
|
||||
return render(request, "zerver/config_error.html", context)
|
||||
return render(request, f"zerver/config_error/{error_name}.html", context)
|
||||
|
|
|
@ -91,7 +91,7 @@ urls = [
|
|||
"devtools/integrations/send_all_webhook_fixture_messages", send_all_webhook_fixture_messages
|
||||
),
|
||||
path("devtools/integrations/<integration_name>/fixtures", get_fixtures),
|
||||
path("config-error/<error_category_name>", config_error, name="config_error"),
|
||||
path("config-error/<error_name>", config_error, name="config_error"),
|
||||
# Special endpoint to remove all the server-side caches.
|
||||
path("flush_caches", remove_caches),
|
||||
# Redirect camo URLs for development
|
||||
|
|
Loading…
Reference in New Issue