remote_billing: Add redirect flow for users with expired session.

Implements a nice redirect flow to give a good UX for users attempting
to access a remote billing page with an expired RemoteRealm session e.g.
/realm/some-uuid/sponsorship - perhaps through their browser
history or just their session expired while they were doing things in
this billing system.

The logic has a few pieces:
1. get_remote_realm_from_session, if the user doesn't have a
   identity_dict will raise RemoteBillingAuthenticationError.
2. If the user has an identity_dict, but it's expired, then
   get_identity_dict_from_session inside of get_remote_realm_from_session
   will raise RemoteBillingIdentityExpiredError.
3. The decorator authenticated_remote_realm_management_endpoint
   catches that exception and uses some general logic, described in more
   detail in the comments in the code, to figure out the right URL to
   redirect them to. Something like:
   https://theirserver.example.com/self-hosted-billing/?next_page=...
   where the next_page param is determined based on parsing request.path
   to see what kind of endpoint they're trying to access.
4. The remote_server_billing_entry endpoint is tweaked to also send
   its uri scheme to the bouncer, so that the bouncer can know whether
   to do the redirect on http or https.
This commit is contained in:
Mateusz Mandera
2023-12-02 22:37:54 +01:00
committed by Tim Abbott
parent 4987600edc
commit ec7245d4e1
6 changed files with 194 additions and 12 deletions

View File

@@ -49,6 +49,7 @@ class ErrorCode(Enum):
MISSING_REMOTE_REALM = auto()
TOPIC_WILDCARD_MENTION_NOT_ALLOWED = auto()
STREAM_WILDCARD_MENTION_NOT_ALLOWED = auto()
REMOTE_BILLING_UNAUTHENTICATED_USER = auto()
class JsonableError(Exception):
@@ -445,6 +446,22 @@ class MissingAuthenticationError(JsonableError):
# converted into json_unauthorized in Zulip's middleware.
class RemoteBillingAuthenticationError(JsonableError):
# We want this as a distinct class from MissingAuthenticationError,
# as we don't want the json_unauthorized conversion mechanism to apply
# to this.
code = ErrorCode.REMOTE_BILLING_UNAUTHENTICATED_USER
http_status_code = 401
def __init__(self) -> None:
pass
@staticmethod
@override
def msg_format() -> str:
return _("User not authenticated")
class InvalidSubdomainError(JsonableError):
code = ErrorCode.NONEXISTENT_SUBDOMAIN
http_status_code = 404