mirror of https://github.com/zulip/zulip.git
support: Add basic support endpoint for remote servers.
This commit is contained in:
parent
2ed1465b04
commit
f71e2c8247
|
@ -25,6 +25,54 @@ from zerver.models import (
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from django.test.client import _MonkeyPatchedWSGIResponse as TestHttpResponse
|
from django.test.client import _MonkeyPatchedWSGIResponse as TestHttpResponse
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from zilencer.models import RemoteZulipServer
|
||||||
|
|
||||||
|
|
||||||
|
class TestRemoteServerSupportEndpoint(ZulipTestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
# Set up some initial example data.
|
||||||
|
for i in range(20):
|
||||||
|
hostname = f"zulip-{i}.example.com"
|
||||||
|
RemoteZulipServer.objects.create(
|
||||||
|
hostname=hostname, contact_email=f"admin@{hostname}", plan_type=1, uuid=uuid.uuid4()
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_search(self) -> None:
|
||||||
|
self.login("cordelia")
|
||||||
|
|
||||||
|
result = self.client_get("/activity/remote/support")
|
||||||
|
self.assertEqual(result.status_code, 302)
|
||||||
|
self.assertEqual(result["Location"], "/login/")
|
||||||
|
|
||||||
|
# Iago is the user with the appropriate permissions to access this page.
|
||||||
|
self.login("iago")
|
||||||
|
assert self.example_user("iago").is_staff
|
||||||
|
|
||||||
|
result = self.client_get("/activity/remote/support")
|
||||||
|
self.assert_in_success_response(
|
||||||
|
[
|
||||||
|
'input type="text" name="q" class="input-xxlarge search-query" placeholder="hostname or contact email"'
|
||||||
|
],
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
|
||||||
|
result = self.client_get("/activity/remote/support", {"q": "zulip-1.example.com"})
|
||||||
|
self.assert_in_success_response(["<h3>zulip-1.example.com</h3>"], result)
|
||||||
|
self.assert_not_in_success_response(["<h3>zulip-2.example.com</h3>"], result)
|
||||||
|
|
||||||
|
result = self.client_get("/activity/remote/support", {"q": "example.com"})
|
||||||
|
for i in range(20):
|
||||||
|
self.assert_in_success_response([f"<h3>zulip-{i}.example.com</h3>"], result)
|
||||||
|
|
||||||
|
result = self.client_get("/activity/remote/support", {"q": "admin@zulip-2.example.com"})
|
||||||
|
self.assert_in_success_response(["<h3>zulip-2.example.com</h3>"], result)
|
||||||
|
self.assert_in_success_response(["<b>Contact email</b>: admin@zulip-2.example.com"], result)
|
||||||
|
self.assert_not_in_success_response(["<h3>zulip-1.example.com</h3>"], result)
|
||||||
|
|
||||||
|
|
||||||
class TestSupportEndpoint(ZulipTestCase):
|
class TestSupportEndpoint(ZulipTestCase):
|
||||||
def test_search(self) -> None:
|
def test_search(self) -> None:
|
||||||
|
|
|
@ -21,7 +21,7 @@ from analytics.views.stats import (
|
||||||
stats_for_remote_installation,
|
stats_for_remote_installation,
|
||||||
stats_for_remote_realm,
|
stats_for_remote_realm,
|
||||||
)
|
)
|
||||||
from analytics.views.support import support
|
from analytics.views.support import remote_servers_support, support
|
||||||
from analytics.views.user_activity import get_user_activity
|
from analytics.views.user_activity import get_user_activity
|
||||||
from zerver.lib.rest import rest_path
|
from zerver.lib.rest import rest_path
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ i18n_urlpatterns: List[Union[URLPattern, URLResolver]] = [
|
||||||
path("activity", get_installation_activity),
|
path("activity", get_installation_activity),
|
||||||
path("activity/remote", get_remote_server_activity),
|
path("activity/remote", get_remote_server_activity),
|
||||||
path("activity/support", support, name="support"),
|
path("activity/support", support, name="support"),
|
||||||
|
path("activity/remote/support", remote_servers_support, name="remote_servers_support"),
|
||||||
path("realm_activity/<realm_str>/", get_realm_activity),
|
path("realm_activity/<realm_str>/", get_realm_activity),
|
||||||
path("user_activity/<user_profile_id>/", get_user_activity),
|
path("user_activity/<user_profile_id>/", get_user_activity),
|
||||||
path("stats/realm/<realm_str>/", stats_for_realm),
|
path("stats/realm/<realm_str>/", stats_for_realm),
|
||||||
|
|
|
@ -17,6 +17,7 @@ from django.utils.timesince import timesince
|
||||||
from django.utils.timezone import now as timezone_now
|
from django.utils.timezone import now as timezone_now
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
from analytics.views.activity_common import remote_installation_stats_link
|
||||||
from confirmation.models import Confirmation, confirmation_url
|
from confirmation.models import Confirmation, confirmation_url
|
||||||
from confirmation.settings import STATUS_USED
|
from confirmation.settings import STATUS_USED
|
||||||
from zerver.actions.create_realm import do_change_realm_subdomain
|
from zerver.actions.create_realm import do_change_realm_subdomain
|
||||||
|
@ -48,6 +49,9 @@ from zerver.models import (
|
||||||
)
|
)
|
||||||
from zerver.views.invite import get_invitee_emails_set
|
from zerver.views.invite import get_invitee_emails_set
|
||||||
|
|
||||||
|
if settings.ZILENCER_ENABLED:
|
||||||
|
from zilencer.models import RemoteZulipServer
|
||||||
|
|
||||||
if settings.BILLING_ENABLED:
|
if settings.BILLING_ENABLED:
|
||||||
from corporate.lib.stripe import approve_sponsorship as do_approve_sponsorship
|
from corporate.lib.stripe import approve_sponsorship as do_approve_sponsorship
|
||||||
from corporate.lib.stripe import (
|
from corporate.lib.stripe import (
|
||||||
|
@ -406,3 +410,44 @@ def support(
|
||||||
)
|
)
|
||||||
|
|
||||||
return render(request, "analytics/support.html", context=context)
|
return render(request, "analytics/support.html", context=context)
|
||||||
|
|
||||||
|
|
||||||
|
def get_remote_servers_for_support(
|
||||||
|
email_to_search: Optional[str], hostname_to_search: Optional[str]
|
||||||
|
) -> List["RemoteZulipServer"]:
|
||||||
|
if not email_to_search and not hostname_to_search:
|
||||||
|
return []
|
||||||
|
|
||||||
|
remote_servers_query = RemoteZulipServer.objects.order_by("id")
|
||||||
|
if email_to_search:
|
||||||
|
remote_servers_query = remote_servers_query.filter(contact_email__iexact=email_to_search)
|
||||||
|
elif hostname_to_search:
|
||||||
|
remote_servers_query = remote_servers_query.filter(hostname__icontains=hostname_to_search)
|
||||||
|
|
||||||
|
return list(remote_servers_query)
|
||||||
|
|
||||||
|
|
||||||
|
@require_server_admin
|
||||||
|
@has_request_variables
|
||||||
|
def remote_servers_support(
|
||||||
|
request: HttpRequest, query: Optional[str] = REQ("q", default=None)
|
||||||
|
) -> HttpResponse:
|
||||||
|
email_to_search = None
|
||||||
|
hostname_to_search = None
|
||||||
|
if query:
|
||||||
|
if "@" in query:
|
||||||
|
email_to_search = query
|
||||||
|
else:
|
||||||
|
hostname_to_search = query
|
||||||
|
|
||||||
|
remote_servers = get_remote_servers_for_support(
|
||||||
|
email_to_search=email_to_search, hostname_to_search=hostname_to_search
|
||||||
|
)
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"analytics/remote_server_support.html",
|
||||||
|
context=dict(
|
||||||
|
remote_servers=remote_servers,
|
||||||
|
remote_installation_stats_link=remote_installation_stats_link,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
{% extends "zerver/base.html" %}
|
||||||
|
{% set entrypoint = "support" %}
|
||||||
|
|
||||||
|
{# Remote servers. #}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
<title>Remote servers</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<br />
|
||||||
|
<form>
|
||||||
|
<center>
|
||||||
|
<input type="text" name="q" class="input-xxlarge search-query" placeholder="hostname or contact email" value="{{ request.GET.get('q', '') }}" autofocus />
|
||||||
|
<button type="submit" class="btn btn-default support-search-button">Search</button>
|
||||||
|
</center>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="remote-server-query-results">
|
||||||
|
{% for remote_server in remote_servers %}
|
||||||
|
<div class="support-query-result">
|
||||||
|
<span class="label">remote server</span>
|
||||||
|
<h3>{{ remote_server.hostname }}</h3>
|
||||||
|
<b>Contact email</b>: {{ remote_server.contact_email }}<br />
|
||||||
|
<b>Last updated</b>: {{ remote_server.last_updated|timesince }} ago<br />
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -548,6 +548,7 @@ html_rules: List["Rule"] = [
|
||||||
},
|
},
|
||||||
"exclude": {
|
"exclude": {
|
||||||
"templates/analytics/support.html",
|
"templates/analytics/support.html",
|
||||||
|
"templates/analytics/remote_server_support.html",
|
||||||
# We have URL template and Pygments language name as placeholders
|
# We have URL template and Pygments language name as placeholders
|
||||||
# in the below template which we don't want to be translatable.
|
# in the below template which we don't want to be translatable.
|
||||||
"web/templates/settings/playground_settings_admin.hbs",
|
"web/templates/settings/playground_settings_admin.hbs",
|
||||||
|
|
Loading…
Reference in New Issue