mirror of https://github.com/zulip/zulip.git
billing: Offer release announcement subscriptions.
Also avoid prompting for full name time more than once. Adds TOS version field to Remote server user. Co-authored-by: Karl Stolley <karl@zulip.com> Co-authored-by: Aman Agrawal <amanagr@zulip.com>
This commit is contained in:
parent
4ef93de128
commit
1757b88760
|
@ -133,6 +133,15 @@ def get_identity_dict_from_signed_access_token(
|
|||
return identity_dict
|
||||
|
||||
|
||||
def is_tos_consent_needed_for_user(
|
||||
remote_user: Union[RemoteRealmBillingUser, RemoteServerBillingUser]
|
||||
) -> bool:
|
||||
assert settings.TERMS_OF_SERVICE_VERSION is not None
|
||||
return int(settings.TERMS_OF_SERVICE_VERSION.split(".")[0]) > int(
|
||||
remote_user.tos_version.split(".")[0]
|
||||
)
|
||||
|
||||
|
||||
@self_hosting_management_endpoint
|
||||
@typed_endpoint
|
||||
def remote_realm_billing_finalize_login(
|
||||
|
@ -141,6 +150,8 @@ def remote_realm_billing_finalize_login(
|
|||
signed_billing_access_token: PathOnly[str],
|
||||
full_name: Optional[str] = None,
|
||||
tos_consent: Literal[None, "true"] = None,
|
||||
enable_major_release_emails: Literal[None, "true", "false"] = None,
|
||||
enable_maintenance_release_emails: Literal[None, "true", "false"] = None,
|
||||
) -> HttpResponse:
|
||||
"""
|
||||
This is the endpoint accessed via the billing_access_url, generated by
|
||||
|
@ -193,9 +204,7 @@ def remote_realm_billing_finalize_login(
|
|||
remote_realm=remote_realm,
|
||||
user_uuid=user_uuid,
|
||||
)
|
||||
tos_consent_needed = int(settings.TERMS_OF_SERVICE_VERSION.split(".")[0]) > int(
|
||||
remote_user.tos_version.split(".")[0]
|
||||
)
|
||||
tos_consent_needed = is_tos_consent_needed_for_user(remote_user)
|
||||
except RemoteRealmBillingUser.DoesNotExist:
|
||||
# This is the first time this user is logging in.
|
||||
remote_user = None
|
||||
|
@ -243,7 +252,7 @@ def remote_realm_billing_finalize_login(
|
|||
# Users logging in for the first time need to be created and follow
|
||||
# a different path - they should not be POSTing here. It should be impossible
|
||||
# to get here with a remote_user that is None without tampering with the form
|
||||
# or manualling crafting a POST request.
|
||||
# or manually crafting a POST request.
|
||||
raise JsonableError(_("User account doesn't exist yet."))
|
||||
|
||||
if tos_consent_needed and not tos_consent_given:
|
||||
|
@ -251,14 +260,25 @@ def remote_realm_billing_finalize_login(
|
|||
# don't need a pretty error.
|
||||
raise JsonableError(_("You must accept the Terms of Service to proceed."))
|
||||
|
||||
# The current approach is to update the full_name
|
||||
# based on what the user entered in the login confirmation form.
|
||||
# Usually they'll presumably just use the name already set for this object.
|
||||
# The current approach is to update the full_name and email preferences
|
||||
# only when the user first logs in.
|
||||
if full_name is not None:
|
||||
remote_user.full_name = full_name
|
||||
remote_user.enable_major_release_emails = enable_major_release_emails == "true"
|
||||
remote_user.enable_maintenance_release_emails = enable_maintenance_release_emails == "true"
|
||||
|
||||
remote_user.tos_version = settings.TERMS_OF_SERVICE_VERSION
|
||||
remote_user.last_login = timezone_now()
|
||||
remote_user.save(update_fields=["full_name", "tos_version", "last_login"])
|
||||
|
||||
remote_user.save(
|
||||
update_fields=[
|
||||
"full_name",
|
||||
"tos_version",
|
||||
"last_login",
|
||||
"enable_maintenance_release_emails",
|
||||
"enable_major_release_emails",
|
||||
]
|
||||
)
|
||||
|
||||
identity_dict["remote_billing_user_id"] = remote_user.id
|
||||
request.session["remote_billing_identities"] = {}
|
||||
|
@ -580,6 +600,8 @@ def remote_billing_legacy_server_from_login_confirmation_link(
|
|||
confirmation_key: PathOnly[str],
|
||||
full_name: Optional[str] = None,
|
||||
tos_consent: Literal[None, "true"] = None,
|
||||
enable_major_release_emails: Literal[None, "true", "false"] = None,
|
||||
enable_maintenance_release_emails: Literal[None, "true", "false"] = None,
|
||||
) -> HttpResponse:
|
||||
"""
|
||||
The user comes here via the confirmation link they received via email.
|
||||
|
@ -602,14 +624,18 @@ def remote_billing_legacy_server_from_login_confirmation_link(
|
|||
|
||||
# If this user (identified by email) already did this flow, meaning the have a RemoteServerBillingUser,
|
||||
# then we don't re-do the ToS consent again.
|
||||
tos_consent_needed = not RemoteServerBillingUser.objects.filter(
|
||||
remote_billing_user = RemoteServerBillingUser.objects.filter(
|
||||
remote_server=remote_server, email=prereg_object.email
|
||||
).exists()
|
||||
).first()
|
||||
tos_consent_needed = remote_billing_user is None or is_tos_consent_needed_for_user(
|
||||
remote_billing_user
|
||||
)
|
||||
|
||||
if request.method == "GET":
|
||||
context = {
|
||||
"remote_server_uuid": remote_server_uuid,
|
||||
"host": remote_server.hostname,
|
||||
"user_full_name": getattr(remote_billing_user, "full_name", None),
|
||||
"user_email": prereg_object.email,
|
||||
"tos_consent_needed": tos_consent_needed,
|
||||
"action_url": reverse(
|
||||
|
@ -632,12 +658,17 @@ 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."))
|
||||
|
||||
remote_billing_user, created = RemoteServerBillingUser.objects.update_or_create(
|
||||
defaults={"full_name": full_name},
|
||||
email=prereg_object.email,
|
||||
remote_server=remote_server,
|
||||
)
|
||||
if created:
|
||||
if remote_billing_user is None:
|
||||
assert full_name is not None
|
||||
assert settings.TERMS_OF_SERVICE_VERSION is not None
|
||||
remote_billing_user = RemoteServerBillingUser.objects.create(
|
||||
full_name=full_name,
|
||||
email=prereg_object.email,
|
||||
remote_server=remote_server,
|
||||
tos_version=settings.TERMS_OF_SERVICE_VERSION,
|
||||
enable_major_release_emails=enable_major_release_emails == "true",
|
||||
enable_maintenance_release_emails=enable_maintenance_release_emails == "true",
|
||||
)
|
||||
prereg_object.created_user = remote_billing_user
|
||||
prereg_object.save(update_fields=["created_user"])
|
||||
|
||||
|
|
|
@ -26,8 +26,14 @@
|
|||
{{ csrf_input }}
|
||||
<div class="input-box remote-billing-confirm-login-form-field">
|
||||
<label for="full_name" class="inline-block label-title">Full name</label>
|
||||
<input id="full_name" name="full_name" class="required" type="text" {% if user_full_name %}value="{{ user_full_name }}"{% endif %} />
|
||||
{% if not user_full_name %}
|
||||
<input id="full_name" name="full_name" class="required" type="text" />
|
||||
<div id="remote-billing-confirm-login-form-full_name-error" class="alert alert-danger remote-billing-confirm-login-form-field-error full_name-error"></div>
|
||||
{% else %}
|
||||
<div class="not-editable-realm-field">
|
||||
{{ user_full_name }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="input-box remote-billing-confirm-login-form-field no-validation">
|
||||
<label for="user-email" class="inline-block label-title">
|
||||
|
@ -37,9 +43,24 @@
|
|||
{{ user_email }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- user_full_name is not present only when user first logs in which also perfect to set email preferences -->
|
||||
{% if not user_full_name %}
|
||||
<div class="input-group remote-billing-confirm-email-subscription-form-field">
|
||||
<label for="enable-major-release-emails" class="checkbox">
|
||||
<input id="enable-major-release-emails" name="enable_major_release_emails" type="checkbox" value="true" checked="checked" />
|
||||
<span></span>
|
||||
Sign me up for emails about <strong>major Zulip releases</strong> and other big announcements (a few times a year)
|
||||
</label>
|
||||
<label for="enable-maintenance-release-emails" class="checkbox">
|
||||
<input id="enable-maintenance-release-emails" name="enable_maintenance_release_emails" type="checkbox" value="true" checked="checked" />
|
||||
<span></span>
|
||||
Sign me up for emails about <strong>all Zulip releases</strong>, including security and maintenance releases (recommended for server administrators)
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if tos_consent_needed %}
|
||||
<div class="input-group terms-of-service remote-billing-confirm-login-form-field" id="remote-billing-confirm-login-tos-wrapper">
|
||||
<label for="remote-billing-confirm-login-tos" class="inline-block checkbox">
|
||||
<label for="remote-billing-confirm-login-tos" class="checkbox">
|
||||
<input id="remote-billing-confirm-login-tos" name="tos_consent" class="required" type="checkbox" value="true" />
|
||||
<span></span>
|
||||
I agree to the <a href="{{ root_domain_url }}/policies/terms" target="_blank" rel="noopener noreferrer">Terms of Service</a>.
|
||||
|
|
|
@ -65,6 +65,20 @@ export function initialize(): void {
|
|||
}
|
||||
},
|
||||
});
|
||||
|
||||
$<HTMLInputElement>("#enable-major-release-emails").on("change", function () {
|
||||
if (this.checked) {
|
||||
$(this).val("true");
|
||||
}
|
||||
$(this).val("false");
|
||||
});
|
||||
|
||||
$<HTMLInputElement>("#enable-maintenance-release-emails").on("change", function () {
|
||||
if (this.checked) {
|
||||
$(this).val("true");
|
||||
}
|
||||
$(this).val("false");
|
||||
});
|
||||
}
|
||||
|
||||
$(() => {
|
||||
|
|
|
@ -731,7 +731,7 @@ input[name="licenses"] {
|
|||
}
|
||||
|
||||
#remote-billing-confirm-login-form #remote-billing-confirm-login-tos-wrapper {
|
||||
margin: 25px auto 10px;
|
||||
margin: 0 auto 10px;
|
||||
}
|
||||
|
||||
#account-deactivated-success-page-details
|
||||
|
|
|
@ -1147,6 +1147,23 @@ button#register_auth_button_gitlab {
|
|||
}
|
||||
}
|
||||
|
||||
.remote-billing-confirm-email-subscription-form-field {
|
||||
width: 450px;
|
||||
margin-top: 15px;
|
||||
|
||||
.checkbox {
|
||||
display: block;
|
||||
/* Present a hanging indent on subscription copy
|
||||
and checkboxes. */
|
||||
text-indent: -26px;
|
||||
margin: 0 0 10px 26px;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.org-url {
|
||||
margin-bottom: 5px !important;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# Generated by Django 4.2.8 on 2023-12-14 17:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("zilencer", "0053_remoterealmauditlog_acting_remote_user_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="remoterealmbillinguser",
|
||||
name="enable_maintenance_release_emails",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="remoterealmbillinguser",
|
||||
name="enable_major_release_emails",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="remoteserverbillinguser",
|
||||
name="enable_maintenance_release_emails",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="remoteserverbillinguser",
|
||||
name="enable_major_release_emails",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 4.2.8 on 2023-12-14 17:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("zilencer", "0054_remoterealmbillinguser_enable_maintenance_release_emails_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="remoteserverbillinguser",
|
||||
name="tos_version",
|
||||
field=models.TextField(default="-1"),
|
||||
),
|
||||
]
|
|
@ -195,6 +195,9 @@ class RemoteRealmBillingUser(AbstractRemoteRealmBillingUser):
|
|||
TOS_VERSION_BEFORE_FIRST_LOGIN = UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN
|
||||
tos_version = models.TextField(default=TOS_VERSION_BEFORE_FIRST_LOGIN)
|
||||
|
||||
enable_major_release_emails = models.BooleanField(default=True)
|
||||
enable_maintenance_release_emails = models.BooleanField(default=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = [
|
||||
("remote_realm", "user_uuid"),
|
||||
|
@ -233,6 +236,12 @@ class RemoteServerBillingUser(AbstractRemoteServerBillingUser):
|
|||
|
||||
is_active = models.BooleanField(default=True)
|
||||
|
||||
TOS_VERSION_BEFORE_FIRST_LOGIN = UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN
|
||||
tos_version = models.TextField(default=TOS_VERSION_BEFORE_FIRST_LOGIN)
|
||||
|
||||
enable_major_release_emails = models.BooleanField(default=True)
|
||||
enable_maintenance_release_emails = models.BooleanField(default=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = [
|
||||
("remote_server", "email"),
|
||||
|
|
Loading…
Reference in New Issue