mirror of
https://github.com/zulip/zulip.git
synced 2025-11-20 22:48:16 +00:00
export: Allow generating export with no usable owner account.
8ab400b95d adds a couple guardrails
againts generating an exporting realm with no usable owner and admin
accounts.
As per #34275, this commit lifts these guardrails to allow generating
export with no usable owner accounts. Export data without usable user
account might still have other uses other than for import.
This commit is contained in:
@@ -3105,30 +3105,3 @@ def do_common_export_processes(output_dir: str) -> None:
|
||||
|
||||
logging.info("Exporting migration status")
|
||||
export_migration_status(output_dir)
|
||||
|
||||
|
||||
def check_export_with_consent_is_usable(realm: Realm) -> bool:
|
||||
# Users without consent enabled will end up deactivated in the exported
|
||||
# data. An organization without a consenting Owner would therefore not be
|
||||
# functional after export->import. That's most likely not desired by the user
|
||||
# so check for such a case.
|
||||
consented_user_ids = get_consented_user_ids(realm)
|
||||
return UserProfile.objects.filter(
|
||||
id__in=consented_user_ids, role=UserProfile.ROLE_REALM_OWNER, realm=realm
|
||||
).exists()
|
||||
|
||||
|
||||
def check_public_export_is_usable(realm: Realm) -> bool:
|
||||
# Since users with email visibility set to NOBODY won't have their real emails
|
||||
# exported, this could result in a lack of functional Owner accounts.
|
||||
# We make sure that at least one Owner can have their real email address exported.
|
||||
return UserProfile.objects.filter(
|
||||
role=UserProfile.ROLE_REALM_OWNER,
|
||||
email_address_visibility__in=[
|
||||
UserProfile.EMAIL_ADDRESS_VISIBILITY_EVERYONE,
|
||||
UserProfile.EMAIL_ADDRESS_VISIBILITY_MEMBERS,
|
||||
UserProfile.EMAIL_ADDRESS_VISIBILITY_MODERATORS,
|
||||
UserProfile.EMAIL_ADDRESS_VISIBILITY_ADMINS,
|
||||
],
|
||||
realm=realm,
|
||||
).exists()
|
||||
|
||||
@@ -9,11 +9,7 @@ from django.utils.timezone import now as timezone_now
|
||||
from typing_extensions import override
|
||||
|
||||
from zerver.actions.realm_settings import do_deactivate_realm
|
||||
from zerver.lib.export import (
|
||||
check_export_with_consent_is_usable,
|
||||
check_public_export_is_usable,
|
||||
export_realm_wrapper,
|
||||
)
|
||||
from zerver.lib.export import export_realm_wrapper
|
||||
from zerver.lib.management import ZulipBaseCommand
|
||||
from zerver.models import RealmExport
|
||||
|
||||
@@ -106,11 +102,6 @@ class Command(ZulipBaseCommand):
|
||||
action="store_true",
|
||||
help="Whether to export private data of users who consented",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--force",
|
||||
action="store_true",
|
||||
help="Skip checks for whether the generated export will be a usable realm.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--upload",
|
||||
action="store_true",
|
||||
@@ -161,15 +152,6 @@ class Command(ZulipBaseCommand):
|
||||
f"Refusing to overwrite existing tarball: {tarball_path}. Aborting..."
|
||||
)
|
||||
|
||||
if (not options["force"]) and (
|
||||
(export_full_with_consent and not check_export_with_consent_is_usable(realm))
|
||||
or (public_only and not check_public_export_is_usable(realm))
|
||||
):
|
||||
raise CommandError(
|
||||
"The generated export will not be a usable organization! "
|
||||
"You can pass --force to skip this check."
|
||||
)
|
||||
|
||||
if options["deactivate_realm"]:
|
||||
print(f"\033[94mDeactivating realm\033[0m: {realm.string_id}")
|
||||
do_deactivate_realm(
|
||||
|
||||
@@ -208,41 +208,6 @@ class RealmExportTest(ZulipTestCase):
|
||||
admin = self.example_user("iago")
|
||||
self.login_user(admin)
|
||||
|
||||
owner = self.example_user("desdemona")
|
||||
do_change_user_setting(
|
||||
owner,
|
||||
"email_address_visibility",
|
||||
UserProfile.EMAIL_ADDRESS_VISIBILITY_NOBODY,
|
||||
acting_user=None,
|
||||
)
|
||||
|
||||
result = self.client_post("/json/export/realm")
|
||||
self.assert_json_error_contains(
|
||||
result,
|
||||
"Make sure at least one Organization Owner allows "
|
||||
"other Administrators to see their email address",
|
||||
)
|
||||
do_change_user_setting(
|
||||
owner,
|
||||
"email_address_visibility",
|
||||
UserProfile.EMAIL_ADDRESS_VISIBILITY_ADMINS,
|
||||
acting_user=None,
|
||||
)
|
||||
|
||||
do_change_user_setting(
|
||||
owner,
|
||||
"allow_private_data_export",
|
||||
False,
|
||||
acting_user=None,
|
||||
)
|
||||
result = self.client_post(
|
||||
"/json/export/realm",
|
||||
info={"export_type": RealmExport.EXPORT_FULL_WITH_CONSENT},
|
||||
)
|
||||
self.assert_json_error_contains(
|
||||
result, "Make sure at least one Organization Owner is consenting"
|
||||
)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"zerver.lib.export.do_export_realm", side_effect=Exception("failure")
|
||||
@@ -383,3 +348,43 @@ class RealmExportTest(ZulipTestCase):
|
||||
self.assertTrue(export_consent["consented"])
|
||||
continue
|
||||
self.assertFalse(export_consent["consented"])
|
||||
|
||||
def test_allow_export_with_no_usable_user_accounts(self) -> None:
|
||||
"""
|
||||
Generating export with no usable accounts should be allowed.
|
||||
"""
|
||||
admin = self.example_user("iago")
|
||||
self.login_user(admin)
|
||||
|
||||
# For standard export, this means no one consented to their
|
||||
# private data being shared.
|
||||
UserProfile.objects.filter(
|
||||
role=UserProfile.ROLE_REALM_OWNER,
|
||||
realm=admin.realm,
|
||||
).update(
|
||||
allow_private_data_export=False,
|
||||
)
|
||||
result = self.client_post(
|
||||
"/json/export/realm",
|
||||
{
|
||||
"export_type": RealmExport.EXPORT_FULL_WITH_CONSENT,
|
||||
},
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
|
||||
# For public export, this means everyone has set their email
|
||||
# address visibility policy to nobody.
|
||||
UserProfile.objects.filter(
|
||||
role=UserProfile.ROLE_REALM_OWNER,
|
||||
realm=admin.realm,
|
||||
).update(
|
||||
email_address_visibility=UserProfile.EMAIL_ADDRESS_VISIBILITY_NOBODY,
|
||||
)
|
||||
|
||||
result = self.client_post(
|
||||
"/json/export/realm",
|
||||
{
|
||||
"export_type": RealmExport.EXPORT_PUBLIC,
|
||||
},
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
|
||||
@@ -11,11 +11,7 @@ from analytics.models import RealmCount
|
||||
from zerver.actions.realm_export import do_delete_realm_export, notify_realm_export
|
||||
from zerver.decorator import require_realm_admin
|
||||
from zerver.lib.exceptions import JsonableError
|
||||
from zerver.lib.export import (
|
||||
check_export_with_consent_is_usable,
|
||||
check_public_export_is_usable,
|
||||
get_realm_exports_serialized,
|
||||
)
|
||||
from zerver.lib.export import get_realm_exports_serialized
|
||||
from zerver.lib.queue import queue_event_on_commit
|
||||
from zerver.lib.response import json_success
|
||||
from zerver.lib.send_email import FromAddress
|
||||
@@ -86,25 +82,6 @@ def export_realm(
|
||||
)
|
||||
)
|
||||
|
||||
if (
|
||||
export_type == RealmExport.EXPORT_FULL_WITH_CONSENT
|
||||
and not check_export_with_consent_is_usable(realm)
|
||||
):
|
||||
raise JsonableError(
|
||||
_(
|
||||
"Make sure at least one Organization Owner is consenting to the export "
|
||||
"or contact {email} for help."
|
||||
).format(email=FromAddress.SUPPORT)
|
||||
)
|
||||
elif export_type == RealmExport.EXPORT_PUBLIC and not check_public_export_is_usable(realm):
|
||||
raise JsonableError(
|
||||
_(
|
||||
"Make sure at least one Organization Owner allows other "
|
||||
"Administrators to see their email address "
|
||||
"or contact {email} for help"
|
||||
).format(email=FromAddress.SUPPORT)
|
||||
)
|
||||
|
||||
row = RealmExport.objects.create(
|
||||
realm=realm,
|
||||
type=export_type,
|
||||
|
||||
Reference in New Issue
Block a user