users: Set tos_version to -1 for users who have not logged-in yet.

We now set tos_version to "-1" for imported users and the ones
created using API or using other methods like LDAP, SCIM and
management commands. This value will help us to allow users to
change email address visibility setting during first login.
This commit is contained in:
Sahil Batra 2023-05-08 12:47:57 +05:30 committed by Tim Abbott
parent f58e3d2cf6
commit 7f01b3fb63
11 changed files with 45 additions and 19 deletions

View File

@ -1059,6 +1059,7 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
validate_email(user_profile.delivery_email) validate_email(user_profile.delivery_email)
validate_email(user_profile.email) validate_email(user_profile.email)
user_profile.set_unusable_password() user_profile.set_unusable_password()
user_profile.tos_version = UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN
UserProfile.objects.bulk_create(user_profiles) UserProfile.objects.bulk_create(user_profiles)
re_map_foreign_keys(data, "zerver_defaultstream", "stream", related_table="stream") re_map_foreign_keys(data, "zerver_defaultstream", "stream", related_table="stream")

View File

@ -270,6 +270,7 @@ class ZulipSCIMUser(SCIMUser):
password, password,
realm, realm,
full_name_new_value, full_name_new_value,
tos_version=UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN,
acting_user=None, acting_user=None,
) )
return return

View File

@ -53,12 +53,14 @@ workflow as `./manage.py create_user`.
create_user_params.password, create_user_params.password,
realm, realm,
create_user_params.full_name, create_user_params.full_name,
# Explicitly set tos_version=None. For servers that # Explicitly set tos_version=-1. This means that users
# have configured Terms of Service, this means that # created via this mechanism would be prompted to set
# users created via this mechanism will be prompted to # the email_address_visibility setting on first login.
# accept the Terms of Service on first login. # For servers that have configured Terms of Service,
# users will also be prompted to accept the Terms of
# Service on first login.
role=UserProfile.ROLE_REALM_OWNER, role=UserProfile.ROLE_REALM_OWNER,
realm_creation=True, realm_creation=True,
tos_version=None, tos_version=UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN,
acting_user=None, acting_user=None,
) )

View File

@ -6,6 +6,7 @@ from django.db.utils import IntegrityError
from zerver.actions.create_user import do_create_user from zerver.actions.create_user import do_create_user
from zerver.lib.management import ZulipBaseCommand from zerver.lib.management import ZulipBaseCommand
from zerver.models import UserProfile
class Command(ZulipBaseCommand): class Command(ZulipBaseCommand):
@ -38,11 +39,13 @@ prompted to accept the Terms of Service the first time they login.
create_user_params.password, create_user_params.password,
realm, realm,
create_user_params.full_name, create_user_params.full_name,
# Explicitly set tos_version=None. For servers that # Explicitly set tos_version=-1. This means that users
# have configured Terms of Service, this means that # created via this mechanism would be prompted to set
# users created via this mechanism will be prompted to # the email_address_visibility setting on first login.
# accept the Terms of Service on first login. # For servers that have configured Terms of Service,
tos_version=None, # users will also be prompted to accept the Terms of
# Service on first login.
tos_version=UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN,
acting_user=None, acting_user=None,
) )
except IntegrityError: except IntegrityError:

View File

@ -3,6 +3,7 @@ from typing import Any, Collection, List
from django.conf import settings from django.conf import settings
from django.core.management.base import CommandError from django.core.management.base import CommandError
from django.db.models import Q
from zerver.lib.management import ZulipBaseCommand from zerver.lib.management import ZulipBaseCommand
from zerver.lib.send_email import send_custom_email from zerver.lib.send_email import send_custom_email
@ -130,7 +131,9 @@ class Command(ZulipBaseCommand):
users = ( users = (
UserProfile.objects.select_related() UserProfile.objects.select_related()
.filter(id__in=[u.id for u in users]) .filter(id__in=[u.id for u in users])
.exclude(tos_version=None) .exclude(
Q(tos_version=None) | Q(tos_version=UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN)
)
) )
send_custom_email(users, target_emails=target_emails, options=options) send_custom_email(users, target_emails=target_emails, options=options)

View File

@ -1814,6 +1814,13 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings): # type
full_name = models.CharField(max_length=MAX_NAME_LENGTH) full_name = models.CharField(max_length=MAX_NAME_LENGTH)
date_joined = models.DateTimeField(default=timezone_now) date_joined = models.DateTimeField(default=timezone_now)
# Terms of Service version number that this user has accepted. We
# use the special value TOS_VERSION_BEFORE_FIRST_LOGIN for users
# whose account was created without direct user interaction (via
# the API or a data import), and null for users whose account is
# fully created on servers that do not have a configured ToS.
TOS_VERSION_BEFORE_FIRST_LOGIN = "-1"
tos_version = models.CharField(null=True, max_length=10) tos_version = models.CharField(null=True, max_length=10)
api_key = models.CharField(max_length=API_KEY_LENGTH) api_key = models.CharField(max_length=API_KEY_LENGTH)

View File

@ -499,7 +499,7 @@ class HomeTest(ZulipTestCase):
user = self.example_user("hamlet") user = self.example_user("hamlet")
self.login_user(user) self.login_user(user)
for user_tos_version in [None, "1.1", "2.0.3.4"]: for user_tos_version in [None, "-1", "1.1", "2.0.3.4"]:
user.tos_version = user_tos_version user.tos_version = user_tos_version
user.save() user.save()
@ -536,7 +536,7 @@ class HomeTest(ZulipTestCase):
user = self.example_user("hamlet") user = self.example_user("hamlet")
self.login_user(user) self.login_user(user)
user.tos_version = None user.tos_version = UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN
user.save() user.save()
with self.settings( with self.settings(

View File

@ -957,6 +957,7 @@ class AdminCreateUserTest(ZulipTestCase):
result = orjson.loads(result.content) result = orjson.loads(result.content)
self.assertEqual(new_user.full_name, "Romeo Montague") self.assertEqual(new_user.full_name, "Romeo Montague")
self.assertEqual(new_user.id, result["user_id"]) self.assertEqual(new_user.id, result["user_id"])
self.assertEqual(new_user.tos_version, UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN)
# Make sure the recipient field is set correctly. # Make sure the recipient field is set correctly.
self.assertEqual( self.assertEqual(

View File

@ -54,7 +54,7 @@ def accounts_accept_terms(request: HttpRequest) -> HttpResponse:
} }
if ( if (
request.user.tos_version is None request.user.tos_version == UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN
and settings.FIRST_TIME_TERMS_OF_SERVICE_TEMPLATE is not None and settings.FIRST_TIME_TERMS_OF_SERVICE_TEMPLATE is not None
): ):
context[ context[

View File

@ -721,11 +721,13 @@ def create_user_backend(
password, password,
realm, realm,
full_name, full_name,
# Explicitly set tos_version=None. For servers that have # Explicitly set tos_version=-1. This means that users
# configured Terms of Service, this means that users created # created via this mechanism would be prompted to set
# via this mechanism will be prompted to accept the Terms of # the email_address_visibility setting on first login.
# For servers that have configured Terms of Service,
# users will also be prompted to accept the Terms of
# Service on first login. # Service on first login.
tos_version=None, tos_version=UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN,
acting_user=user_profile, acting_user=user_profile,
) )
return json_success(request, data={"user_id": target_user.id}) return json_success(request, data={"user_id": target_user.id})

View File

@ -1047,7 +1047,13 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase):
opts["default_stream_groups"] = [] opts["default_stream_groups"] = []
user_profile = do_create_user( user_profile = do_create_user(
username, None, self._realm, full_name, acting_user=None, **opts username,
None,
self._realm,
full_name,
tos_version=UserProfile.TOS_VERSION_BEFORE_FIRST_LOGIN,
acting_user=None,
**opts,
) )
self.sync_avatar_from_ldap(user_profile, ldap_user) self.sync_avatar_from_ldap(user_profile, ldap_user)
self.sync_custom_profile_fields_from_ldap(user_profile, ldap_user) self.sync_custom_profile_fields_from_ldap(user_profile, ldap_user)