remote_billing: Implement confirmation flow for RemoteRealm auth.

The way the flow goes now is this:
1. The user initiaties login via "Billing" in the gear menu.
2. That takes them to `/self-hosted-billing/` (possibly with a
   `next_page` param if we use that for some gear menu options).
3. The server queries the bouncer to give the user a link with a signed
   access token.
4. The user is redirected to that link (on `selfhosting.zulipchat.com`).
Now we have two cases, either the user is logging in for the first time
and already did in the past.
If this is the first time, we have:
5. The user is asked to fill in their email in a form that's shown,
   pre-filled with the value provided inside the signed access token.
   They POST this to the next endpoint.
6. The next endpoint sends a confirmation email to that address and asks
   the user to go check their email.
7. The user clicks the link in their email is taken to the
   from_confirmation endpoint.
8. Their initial RemoteBillingUser is created, a new signed link like in
   (3) is generated and they're transparently taken back to (4),
   where now that they have a RemoteBillingUser, they're handled
   just like a user who already logged in before:
If the user already logged in before, they go straight here:
9. "Confirm login" page - they're shown their information (email and
   full_name), can update
   their full name in the form if they want. They also accept ToS here
   if necessary. They POST this form back to
   the endpoint and finally have a logged in session.
10. They're redirected to billing (or `next_page`) now that they have
    access.
This commit is contained in:
Mateusz Mandera
2023-12-10 17:10:56 +01:00
committed by Tim Abbott
parent 18ec4cd198
commit 423aebf98e
14 changed files with 442 additions and 69 deletions

View File

@@ -31,7 +31,10 @@ from zerver.models import (
)
if settings.ZILENCER_ENABLED:
from zilencer.models import PreregistrationRemoteServerBillingUser
from zilencer.models import (
PreregistrationRemoteRealmBillingUser,
PreregistrationRemoteServerBillingUser,
)
class ConfirmationKeyError(Exception):
@@ -68,7 +71,9 @@ NoZilencerConfirmationObjT: TypeAlias = Union[
RealmReactivationStatus,
]
ZilencerConfirmationObjT: TypeAlias = Union[
NoZilencerConfirmationObjT, "PreregistrationRemoteServerBillingUser"
NoZilencerConfirmationObjT,
"PreregistrationRemoteServerBillingUser",
"PreregistrationRemoteRealmBillingUser",
]
ConfirmationObjT = Union[NoZilencerConfirmationObjT, ZilencerConfirmationObjT]
@@ -197,6 +202,7 @@ class Confirmation(models.Model):
REALM_CREATION = 7
REALM_REACTIVATION = 8
REMOTE_SERVER_BILLING_LEGACY_LOGIN = 9
REMOTE_REALM_BILLING_LEGACY_LOGIN = 10
type = models.PositiveSmallIntegerField()
class Meta:
@@ -237,6 +243,9 @@ if settings.ZILENCER_ENABLED:
_properties[Confirmation.REMOTE_SERVER_BILLING_LEGACY_LOGIN] = ConfirmationType(
"remote_billing_legacy_server_from_login_confirmation_link"
)
_properties[Confirmation.REMOTE_REALM_BILLING_LEGACY_LOGIN] = ConfirmationType(
"remote_realm_billing_from_login_confirmation_link"
)
def one_click_unsubscribe_link(user_profile: UserProfile, email_type: str) -> str: