mirror of
https://github.com/zulip/zulip.git
synced 2026-07-06 21:18:58 +08:00
remote-support: Add ability to deactivate and reactivate remote servers.
This commit is contained in:
parent
33484e7ac3
commit
f3906f4a2f
@ -573,6 +573,70 @@ class TestRemoteServerSupportEndpoint(ZulipTestCase):
|
||||
self.assertEqual(plan.tier, CustomerPlan.TIER_SELF_HOSTED_LEGACY)
|
||||
self.assertEqual(next_plan.tier, CustomerPlan.TIER_SELF_HOSTED_BASIC)
|
||||
|
||||
def test_support_deactivate_remote_server(self) -> None:
|
||||
iago = self.example_user("iago")
|
||||
self.login_user(iago)
|
||||
|
||||
# A remote server cannot be deactivated when an upgrade is scheduled.
|
||||
remote_server_with_upgrade = RemoteZulipServer.objects.get(hostname="zulip-4.example.com")
|
||||
self.assertFalse(remote_server_with_upgrade.deactivated)
|
||||
result = self.client_post(
|
||||
"/activity/remote/support",
|
||||
{
|
||||
"remote_server_id": f"{remote_server_with_upgrade.id}",
|
||||
"remote_server_status": "deactivated",
|
||||
},
|
||||
)
|
||||
self.assert_in_success_response(
|
||||
[
|
||||
f"Cannot deactivate remote server ({remote_server_with_upgrade.hostname}) that has active or scheduled plans."
|
||||
],
|
||||
result,
|
||||
)
|
||||
remote_server_with_upgrade.refresh_from_db()
|
||||
self.assertFalse(remote_server_with_upgrade.deactivated)
|
||||
|
||||
remote_server_no_upgrade = RemoteZulipServer.objects.get(hostname="zulip-5.example.com")
|
||||
self.assertFalse(remote_server_no_upgrade.deactivated)
|
||||
result = self.client_post(
|
||||
"/activity/remote/support",
|
||||
{
|
||||
"remote_server_id": f"{remote_server_no_upgrade.id}",
|
||||
"remote_server_status": "deactivated",
|
||||
},
|
||||
)
|
||||
self.assert_in_success_response(
|
||||
[f"Remote server ({remote_server_no_upgrade.hostname}) deactivated."], result
|
||||
)
|
||||
remote_server_no_upgrade.refresh_from_db()
|
||||
self.assertTrue(remote_server_no_upgrade.deactivated)
|
||||
audit_log = RemoteZulipServerAuditLog.objects.filter(
|
||||
event_type=RemoteZulipServerAuditLog.REMOTE_SERVER_DEACTIVATED
|
||||
).last()
|
||||
assert audit_log is not None
|
||||
self.assertEqual(audit_log.server, remote_server_no_upgrade)
|
||||
|
||||
def test_support_reactivate_remote_server(self) -> None:
|
||||
iago = self.example_user("iago")
|
||||
self.login_user(iago)
|
||||
|
||||
remote_server = RemoteZulipServer.objects.get(hostname="zulip-0.example.com")
|
||||
self.assertTrue(remote_server.deactivated)
|
||||
result = self.client_post(
|
||||
"/activity/remote/support",
|
||||
{"remote_server_id": f"{remote_server.id}", "remote_server_status": "active"},
|
||||
)
|
||||
self.assert_in_success_response(
|
||||
[f"Remote server ({remote_server.hostname}) reactivated."], result
|
||||
)
|
||||
remote_server.refresh_from_db()
|
||||
self.assertFalse(remote_server.deactivated)
|
||||
audit_log = RemoteZulipServerAuditLog.objects.filter(
|
||||
event_type=RemoteZulipServerAuditLog.REMOTE_SERVER_REACTIVATED
|
||||
).last()
|
||||
assert audit_log is not None
|
||||
self.assertEqual(audit_log.server, remote_server)
|
||||
|
||||
|
||||
class TestSupportEndpoint(ZulipTestCase):
|
||||
def create_customer_and_plan(self, realm: Realm, monthly: bool = False) -> Customer:
|
||||
|
||||
@ -26,10 +26,13 @@ from corporate.lib.stripe import (
|
||||
RealmBillingSession,
|
||||
RemoteRealmBillingSession,
|
||||
RemoteServerBillingSession,
|
||||
ServerDeactivateWithExistingPlanError,
|
||||
SupportRequestError,
|
||||
SupportType,
|
||||
SupportViewRequest,
|
||||
cents_to_dollar_string,
|
||||
do_deactivate_remote_server,
|
||||
do_reactivate_remote_server,
|
||||
format_discount_percentage,
|
||||
)
|
||||
from corporate.lib.support import (
|
||||
@ -534,6 +537,9 @@ def remote_servers_support(
|
||||
default=None, str_validator=check_string_in(VALID_MODIFY_PLAN_METHODS)
|
||||
),
|
||||
delete_fixed_price_next_plan: bool = REQ(default=False, json_validator=check_bool),
|
||||
remote_server_status: Optional[str] = REQ(
|
||||
default=None, str_validator=check_string_in(VALID_STATUS_VALUES)
|
||||
),
|
||||
) -> HttpResponse:
|
||||
context: Dict[str, Any] = {}
|
||||
|
||||
@ -608,6 +614,28 @@ def remote_servers_support(
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.delete_fixed_price_next_plan,
|
||||
)
|
||||
elif remote_server_status:
|
||||
assert remote_server is not None
|
||||
remote_server_status_billing_session = RemoteServerBillingSession(
|
||||
support_staff=acting_user, remote_server=remote_server
|
||||
)
|
||||
if remote_server_status == "active":
|
||||
do_reactivate_remote_server(remote_server)
|
||||
context["success_message"] = (
|
||||
f"Remote server ({remote_server.hostname}) reactivated."
|
||||
)
|
||||
else:
|
||||
assert remote_server_status == "deactivated"
|
||||
try:
|
||||
do_deactivate_remote_server(remote_server, remote_server_status_billing_session)
|
||||
context["success_message"] = (
|
||||
f"Remote server ({remote_server.hostname}) deactivated."
|
||||
)
|
||||
except ServerDeactivateWithExistingPlanError:
|
||||
context["error_message"] = (
|
||||
f"Cannot deactivate remote server ({remote_server.hostname}) that has active or scheduled plans."
|
||||
)
|
||||
|
||||
if support_view_request is not None:
|
||||
if remote_realm_support_request:
|
||||
try:
|
||||
|
||||
@ -146,6 +146,22 @@
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if remote_server.deactivated %}
|
||||
<form method="POST" class="reactivate-remote-server-form">
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="remote_server_id" value="{{ remote_server.id }}" />
|
||||
<input type="hidden" name="remote_server_status" value="active" />
|
||||
<button class="reactivate-remote-server-button"><b>Reactivate</b>: {{ remote_server.hostname }}</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<form method="POST" class="deactivate-remote-server-form">
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="remote_server_id" value="{{ remote_server.id }}" />
|
||||
<input type="hidden" name="remote_server_status" value="deactivated" />
|
||||
<button class="deactivate-remote-server-button"><b>Deactivate</b>: {{ remote_server.hostname }}</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="remote-realms-section">
|
||||
{% if remote_realms[remote_server.id] == [] %}
|
||||
|
||||
@ -171,6 +171,8 @@ tr.admin td:first-child {
|
||||
}
|
||||
}
|
||||
|
||||
.reactivate-remote-server-button,
|
||||
.deactivate-remote-server-button,
|
||||
.delete-next-fixed-price-plan-button,
|
||||
.approve-sponsorship-button,
|
||||
.support-search-button,
|
||||
@ -243,6 +245,7 @@ tr.admin td:first-child {
|
||||
}
|
||||
}
|
||||
|
||||
.deactivate-remote-server-button,
|
||||
.delete-next-fixed-price-plan-button,
|
||||
.delete-user-button,
|
||||
.scrub-realm-button {
|
||||
@ -260,6 +263,30 @@ tr.admin td:first-child {
|
||||
}
|
||||
}
|
||||
|
||||
.reactivate-remote-server-button {
|
||||
color: hsl(0deg 0% 100%);
|
||||
background-color: hsl(35deg 70% 56%);
|
||||
border: 1px solid hsl(35deg 70% 50%);
|
||||
border-radius: 2px;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
color: hsl(0deg 0% 100%);
|
||||
background-color: hsl(35deg 82% 40%);
|
||||
border: 1px solid hsl(35deg 82% 30%);
|
||||
}
|
||||
}
|
||||
|
||||
.reactivate-remote-server-button,
|
||||
.deactivate-remote-server-button {
|
||||
font-size: 15px;
|
||||
line-height: 1.8;
|
||||
max-width: 550px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.remote-support-query-result.remote-server-deactivated {
|
||||
background-color: hsl(2deg 64% 58%);
|
||||
|
||||
@ -280,6 +307,8 @@ tr.admin td:first-child {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.reactivate-remote-server-form,
|
||||
.deactivate-remote-server-form,
|
||||
.realm-support-information,
|
||||
.remote-server-information,
|
||||
.remote-realm-information {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user