From ba80084ea7abe5a4b7d5b73dd4dc9795995f0d29 Mon Sep 17 00:00:00 2001 From: Alya Abbott <2090066+alya@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:25:12 -0800 Subject: [PATCH] remote_billing_page: Deny login for server / remote realm. If server has plan, deny login for realm. If realm has plan, deny login for server. Co-authored-by: Aman Agrawal Co-authored-by: Alya Abbott --- corporate/views/remote_billing_page.py | 40 +++++++++++++++++++ ...login_error_for_server_on_active_plan.html | 39 ++++++++++++++++++ ...in_error_for_any_realm_on_active_plan.html | 34 ++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 templates/corporate/remote_realm_login_error_for_server_on_active_plan.html create mode 100644 templates/corporate/remote_server_login_error_for_any_realm_on_active_plan.html diff --git a/corporate/views/remote_billing_page.py b/corporate/views/remote_billing_page.py index b53420699d..e380f50e97 100644 --- a/corporate/views/remote_billing_page.py +++ b/corporate/views/remote_billing_page.py @@ -5,6 +5,7 @@ from urllib.parse import urlsplit, urlunsplit from django.conf import settings from django.core import signing from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Exists, OuterRef from django.http import HttpRequest, HttpResponse, HttpResponseNotAllowed, HttpResponseRedirect from django.shortcuts import render from django.urls import reverse @@ -35,6 +36,11 @@ from corporate.lib.stripe import ( RemoteRealmBillingSession, RemoteServerBillingSession, ) +from corporate.models import ( + CustomerPlan, + get_current_plan_by_customer, + get_customer_by_remote_server, +) from zerver.lib.exceptions import ( JsonableError, MissingRemoteRealmError, @@ -190,6 +196,19 @@ def remote_realm_billing_finalize_login( # pretty recently. (And we generally don't delete these at all.) raise AssertionError + # Redirect to error page if server is on an active plan + server_customer = get_customer_by_remote_server(remote_server) + if server_customer is not None: + server_plan = get_current_plan_by_customer(server_customer) + if server_plan is not None: + return render( + request, + "corporate/remote_realm_login_error_for_server_on_active_plan.html", + context={ + "server_plan_name": server_plan.name, + }, + ) + user_dict = identity_dict["user"] user_email = user_dict["user_email"] @@ -592,6 +611,21 @@ def remote_billing_legacy_server_confirm_login( ) +def has_live_plan_for_any_remote_realm_on_server(server: RemoteZulipServer) -> bool: + has_plan_with_status_lt_live_threshold = CustomerPlan.objects.filter( + customer__remote_realm__server=server, + status__lt=CustomerPlan.LIVE_STATUS_THRESHOLD, + customer__remote_realm=OuterRef("pk"), + ) + + return ( + RemoteRealm.objects.filter(server=server) + .annotate(has_plan=Exists(has_plan_with_status_lt_live_threshold)) + .filter(has_plan=True) + .exists() + ) + + @self_hosting_management_endpoint @typed_endpoint def remote_billing_legacy_server_from_login_confirmation_link( @@ -658,6 +692,12 @@ def remote_billing_legacy_server_from_login_confirmation_link( # don't need a pretty error. raise JsonableError(_("You must accept the Terms of Service to proceed.")) + if has_live_plan_for_any_remote_realm_on_server(remote_server): + return render( + request, + "corporate/remote_server_login_error_for_any_realm_on_active_plan.html", + ) + if remote_billing_user is None: assert full_name is not None assert settings.TERMS_OF_SERVICE_VERSION is not None diff --git a/templates/corporate/remote_realm_login_error_for_server_on_active_plan.html b/templates/corporate/remote_realm_login_error_for_server_on_active_plan.html new file mode 100644 index 0000000000..401866243a --- /dev/null +++ b/templates/corporate/remote_realm_login_error_for_server_on_active_plan.html @@ -0,0 +1,39 @@ +{% extends "zerver/portico.html" %} + +{% block title %} +{{ _("Plan management not available") }} | Zulip +{% endblock %} + +{% block portico_class_name %}error{% endblock %} + +{% block portico_content %} +
+
+
+ +
+
+

{{ _("Plan management not available") }}

+

+ {% trans %} Plan management is not available for this + organization, because your Zulip server is already on a + {{ server_plan_name }} plan, which covers all + organizations on this server. Follow the log + in instructions + for All older versions + of the Zulip server to manage your plan. + {% endtrans %} +

+

+ {% trans %} To move the plan from the server to this + organization, or for other questions, contact support. + {% endtrans %} +

+
+
+
+
+
+{% endblock %} diff --git a/templates/corporate/remote_server_login_error_for_any_realm_on_active_plan.html b/templates/corporate/remote_server_login_error_for_any_realm_on_active_plan.html new file mode 100644 index 0000000000..989894d635 --- /dev/null +++ b/templates/corporate/remote_server_login_error_for_any_realm_on_active_plan.html @@ -0,0 +1,34 @@ +{% extends "zerver/portico.html" %} + +{% block title %} +{{ _("Plan management not available") }} | Zulip +{% endblock %} + +{% block portico_class_name %}error{% endblock %} + +{% block portico_content %} +
+
+
+ +
+
+

{{ _("Plan management not available") }}

+

+ {% trans %} + Plan management for this server is not available because at least one organization + hosted on this server already has an active plan. + {% endtrans %} +

+

+ {% trans %} + Log in to plan management for your + organization instead, or contact support with any questions. + {% endtrans %} +

+
+
+
+
+
+{% endblock %}