remote_upgrade_page: Add /upgrade URL for self hosted realms.

This commit is contained in:
Aman Agrawal
2023-11-24 08:12:17 +00:00
committed by Tim Abbott
parent caf2b7da26
commit 3cfcd0efee
5 changed files with 78 additions and 2 deletions

View File

@@ -4,6 +4,9 @@ from typing import Optional, TypedDict
from django.http import HttpRequest from django.http import HttpRequest
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from zerver.lib.exceptions import JsonableError
from zilencer.models import RemoteRealm
billing_logger = logging.getLogger("corporate.stripe") billing_logger = logging.getLogger("corporate.stripe")
@@ -28,3 +31,35 @@ def get_identity_dict_from_session(
return identity_dicts.get(authed_uuid) return identity_dicts.get(authed_uuid)
return None return None
def get_remote_realm_from_session(
request: HttpRequest,
realm_uuid: Optional[str],
server_uuid: Optional[str] = None,
) -> RemoteRealm:
identity_dict = get_identity_dict_from_session(request, realm_uuid, server_uuid)
if identity_dict is None:
raise JsonableError(_("User not authenticated"))
remote_server_uuid = identity_dict["remote_server_uuid"]
remote_realm_uuid = identity_dict["remote_realm_uuid"]
try:
remote_realm = RemoteRealm.objects.get(
uuid=remote_realm_uuid, server__uuid=remote_server_uuid
)
except RemoteRealm.DoesNotExist:
raise AssertionError(
"The remote realm is missing despite being in the RemoteBillingIdentityDict"
)
if (
remote_realm.registration_deactivated
or remote_realm.realm_deactivated
or remote_realm.server.deactivated
):
raise JsonableError(_("Registration is deactivated"))
return remote_realm

View File

@@ -1846,6 +1846,14 @@ class RemoteRealmBillingSession(BillingSession): # nocoverage
# TBD # TBD
pass pass
@override
def is_sponsored_or_pending(self, customer: Optional[Customer]) -> bool:
if (
customer is not None and customer.sponsorship_pending
) or self.remote_realm.plan_type == self.remote_realm.PLAN_TYPE_COMMUNITY:
return True
return False
@override @override
def get_upgrade_page_session_type_specific_context( def get_upgrade_page_session_type_specific_context(
self, self,

View File

@@ -27,7 +27,7 @@ from corporate.views.session import (
start_card_update_stripe_session_for_realm_upgrade, start_card_update_stripe_session_for_realm_upgrade,
) )
from corporate.views.support import support_request from corporate.views.support import support_request
from corporate.views.upgrade import sponsorship, upgrade, upgrade_page from corporate.views.upgrade import remote_realm_upgrade_page, sponsorship, upgrade, upgrade_page
from corporate.views.webhook import stripe_webhook from corporate.views.webhook import stripe_webhook
from zerver.lib.rest import rest_path from zerver.lib.rest import rest_path
from zerver.lib.url_redirects import LANDING_PAGE_REDIRECTS from zerver.lib.url_redirects import LANDING_PAGE_REDIRECTS
@@ -168,4 +168,5 @@ urlpatterns += [
), ),
path("realm/<realm_uuid>/billing", remote_billing_page_realm, name="remote_billing_page_realm"), path("realm/<realm_uuid>/billing", remote_billing_page_realm, name="remote_billing_page_realm"),
path("server/<server_uuid>/", remote_billing_page_server, name="remote_billing_page_server"), path("server/<server_uuid>/", remote_billing_page_server, name="remote_billing_page_server"),
path("realm/<realm_uuid>/upgrade", remote_realm_upgrade_page, name="remote_realm_upgrade_page"),
] ]

View File

@@ -6,7 +6,9 @@ from django.conf import settings
from django.db import transaction from django.db import transaction
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render
from pydantic import Json
from corporate.lib.remote_billing_util import get_remote_realm_from_session
from corporate.lib.stripe import ( from corporate.lib.stripe import (
VALID_BILLING_MODALITY_VALUES, VALID_BILLING_MODALITY_VALUES,
VALID_BILLING_SCHEDULE_VALUES, VALID_BILLING_SCHEDULE_VALUES,
@@ -14,15 +16,21 @@ from corporate.lib.stripe import (
BillingError, BillingError,
InitialUpgradeRequest, InitialUpgradeRequest,
RealmBillingSession, RealmBillingSession,
RemoteRealmBillingSession,
UpgradeRequest, UpgradeRequest,
) )
from corporate.lib.support import get_support_url from corporate.lib.support import get_support_url
from corporate.models import CustomerPlan, ZulipSponsorshipRequest from corporate.models import CustomerPlan, ZulipSponsorshipRequest
from zerver.actions.users import do_change_is_billing_admin from zerver.actions.users import do_change_is_billing_admin
from zerver.decorator import require_organization_member, zulip_login_required from zerver.decorator import (
require_organization_member,
self_hosting_management_endpoint,
zulip_login_required,
)
from zerver.lib.request import REQ, has_request_variables from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success from zerver.lib.response import json_success
from zerver.lib.send_email import FromAddress, send_email from zerver.lib.send_email import FromAddress, send_email
from zerver.lib.typed_endpoint import PathOnly, typed_endpoint
from zerver.lib.validator import check_bool, check_int, check_string_in from zerver.lib.validator import check_bool, check_int, check_string_in
from zerver.models import UserProfile, get_org_type_display_name from zerver.models import UserProfile, get_org_type_display_name
@@ -102,6 +110,29 @@ def upgrade_page(
return response return response
@self_hosting_management_endpoint
@typed_endpoint
def remote_realm_upgrade_page(
request: HttpRequest,
*,
realm_uuid: PathOnly[str],
manual_license_management: Json[bool] = False,
) -> HttpResponse: # nocoverage
remote_realm = get_remote_realm_from_session(request, realm_uuid)
initial_upgrade_request = InitialUpgradeRequest(
manual_license_management=manual_license_management,
tier=CustomerPlan.STANDARD,
)
billing_session = RemoteRealmBillingSession(remote_realm)
redirect_url, context = billing_session.get_initial_upgrade_context(initial_upgrade_request)
if redirect_url:
return HttpResponseRedirect(redirect_url)
response = render(request, "corporate/upgrade.html", context=context)
return response
class SponsorshipRequestForm(forms.Form): class SponsorshipRequestForm(forms.Form):
website = forms.URLField(max_length=ZulipSponsorshipRequest.MAX_ORG_URL_LENGTH, required=False) website = forms.URLField(max_length=ZulipSponsorshipRequest.MAX_ORG_URL_LENGTH, required=False)
organization_type = forms.IntegerField() organization_type = forms.IntegerField()

View File

@@ -57,6 +57,7 @@ not_yet_fully_covered = [
# TODO: This is a work in progress and therefore without # TODO: This is a work in progress and therefore without
# tests yet. # tests yet.
"corporate/views/remote_billing_page.py", "corporate/views/remote_billing_page.py",
"corporate/lib/remote_billing_util.py",
# Major lib files should have 100% coverage # Major lib files should have 100% coverage
"zerver/actions/presence.py", "zerver/actions/presence.py",
"zerver/lib/addressee.py", "zerver/lib/addressee.py",