mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
export: Add guardrails against generating a dysfunctional export via UI.
As explained in the comments, if in an export with consent there are no consenting owners or in a public export there are no owners with email visibility set to at least ADMINS, the exported data will, upon import, create an organization without usable owner accounts.
This commit is contained in:
committed by
Tim Abbott
parent
9864eee029
commit
8ab400b95d
@@ -208,6 +208,41 @@ 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")
|
||||
|
@@ -1,7 +1,6 @@
|
||||
from datetime import timedelta
|
||||
from typing import Annotated
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.timezone import now as timezone_now
|
||||
@@ -12,9 +11,10 @@ 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 get_realm_exports_serialized
|
||||
from zerver.lib.export import get_consented_user_ids, 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
|
||||
from zerver.lib.typed_endpoint import typed_endpoint
|
||||
from zerver.lib.typed_endpoint_validators import check_int_in_validator
|
||||
from zerver.models import RealmExport, UserProfile
|
||||
@@ -78,10 +78,48 @@ def export_realm(
|
||||
):
|
||||
raise JsonableError(
|
||||
_("Please request a manual export from {email}.").format(
|
||||
email=settings.ZULIP_ADMINISTRATOR,
|
||||
email=FromAddress.SUPPORT,
|
||||
)
|
||||
)
|
||||
|
||||
if export_type == RealmExport.EXPORT_FULL_WITH_CONSENT:
|
||||
# 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 and return an error.
|
||||
consented_user_ids = get_consented_user_ids(realm)
|
||||
if not UserProfile.objects.filter(
|
||||
id__in=consented_user_ids, role=UserProfile.ROLE_REALM_OWNER, realm=realm
|
||||
).exists():
|
||||
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:
|
||||
# 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
|
||||
# or return an error.
|
||||
if not 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():
|
||||
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