mirror of https://github.com/zulip/zulip.git
realm_export: Add realm_export_consent feature to API.
Fixes part of #31201.
This commit is contained in:
parent
70b6e46516
commit
eaee5763d6
|
@ -20,6 +20,12 @@ format used by the Zulip server that they are interacting with.
|
||||||
|
|
||||||
## Changes in Zulip 10.0
|
## Changes in Zulip 10.0
|
||||||
|
|
||||||
|
**Feature level 312**
|
||||||
|
|
||||||
|
* [`GET /events`](/api/get-events): Added `realm_export_consent` event
|
||||||
|
type to allow realm administrators to view which users have
|
||||||
|
consented to export their private data as part of a realm export.
|
||||||
|
|
||||||
**Feature level 311**
|
**Feature level 311**
|
||||||
|
|
||||||
* [`POST /user_groups/{user_group_id}/members`](/api/update-user-group-members):
|
* [`POST /user_groups/{user_group_id}/members`](/api/update-user-group-members):
|
||||||
|
|
|
@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
||||||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||||
|
|
||||||
API_FEATURE_LEVEL = 311 # Last bumped for updating subgroups.
|
API_FEATURE_LEVEL = 312 # Last bumped for adding 'realm_export_consent' event type.
|
||||||
|
|
||||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
||||||
# only when going from an old version of the code to a newer version. Bump
|
# only when going from an old version of the code to a newer version. Bump
|
||||||
|
|
|
@ -731,6 +731,18 @@ def do_reactivate_user(user_profile: UserProfile, *, acting_user: UserProfile |
|
||||||
)
|
)
|
||||||
send_event_on_commit(user_profile.realm, event, get_user_ids_who_can_access_user(user_profile))
|
send_event_on_commit(user_profile.realm, event, get_user_ids_who_can_access_user(user_profile))
|
||||||
|
|
||||||
|
if not user_profile.is_bot:
|
||||||
|
realm_export_consent_event = dict(
|
||||||
|
type="realm_export_consent",
|
||||||
|
user_id=user_profile.id,
|
||||||
|
consented=user_profile.allow_private_data_export,
|
||||||
|
)
|
||||||
|
send_event_on_commit(
|
||||||
|
user_profile.realm,
|
||||||
|
realm_export_consent_event,
|
||||||
|
list(user_profile.realm.get_human_admin_users().values_list("id", flat=True)),
|
||||||
|
)
|
||||||
|
|
||||||
if user_profile.is_bot:
|
if user_profile.is_bot:
|
||||||
event = dict(
|
event = dict(
|
||||||
type="realm_bot",
|
type="realm_bot",
|
||||||
|
|
|
@ -512,6 +512,18 @@ def do_change_user_setting(
|
||||||
|
|
||||||
send_event_on_commit(user_profile.realm, legacy_event, [user_profile.id])
|
send_event_on_commit(user_profile.realm, legacy_event, [user_profile.id])
|
||||||
|
|
||||||
|
if setting_name == "allow_private_data_export":
|
||||||
|
event = {
|
||||||
|
"type": "realm_export_consent",
|
||||||
|
"user_id": user_profile.id,
|
||||||
|
"consented": setting_value,
|
||||||
|
}
|
||||||
|
send_event_on_commit(
|
||||||
|
user_profile.realm,
|
||||||
|
event,
|
||||||
|
list(user_profile.realm.get_human_admin_users().values_list("id", flat=True)),
|
||||||
|
)
|
||||||
|
|
||||||
# Updates to the time zone display setting are sent to all users
|
# Updates to the time zone display setting are sent to all users
|
||||||
if setting_name == "timezone":
|
if setting_name == "timezone":
|
||||||
payload = dict(
|
payload = dict(
|
||||||
|
|
|
@ -872,6 +872,15 @@ def check_realm_export(
|
||||||
assert has_failed_timestamp == (export["failed_timestamp"] is not None)
|
assert has_failed_timestamp == (export["failed_timestamp"] is not None)
|
||||||
|
|
||||||
|
|
||||||
|
realm_export_consent_event = event_dict_type(
|
||||||
|
[
|
||||||
|
("type", Equals("realm_export_consent")),
|
||||||
|
("user_id", int),
|
||||||
|
("consented", bool),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check_realm_export_consent = make_checker(realm_export_consent_event)
|
||||||
|
|
||||||
realm_linkifier_type = DictType(
|
realm_linkifier_type = DictType(
|
||||||
required_keys=[
|
required_keys=[
|
||||||
("pattern", str),
|
("pattern", str),
|
||||||
|
|
|
@ -1564,6 +1564,10 @@ def apply_event(
|
||||||
# These realm export events are only available to
|
# These realm export events are only available to
|
||||||
# administrators, and aren't included in page_params.
|
# administrators, and aren't included in page_params.
|
||||||
pass
|
pass
|
||||||
|
elif event["type"] == "realm_export_consent":
|
||||||
|
# These 'realm_export_consent' events are only available to
|
||||||
|
# administrators, and aren't included in page_params.
|
||||||
|
pass
|
||||||
elif event["type"] == "alert_words":
|
elif event["type"] == "alert_words":
|
||||||
state["alert_words"] = event["alert_words"]
|
state["alert_words"] = event["alert_words"]
|
||||||
elif event["type"] == "muted_topics":
|
elif event["type"] == "muted_topics":
|
||||||
|
|
|
@ -3884,6 +3884,41 @@ paths:
|
||||||
],
|
],
|
||||||
"id": 1,
|
"id": 1,
|
||||||
}
|
}
|
||||||
|
- type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: |
|
||||||
|
Event sent to administrators when the [data export
|
||||||
|
consent][help-export-consent] status for a user changes, whether due
|
||||||
|
to a user changing their consent preferences or a user being created
|
||||||
|
or reactivated (since user creation/activation events do not contain
|
||||||
|
these data).
|
||||||
|
|
||||||
|
[help-export-consent]: /help/export-your-organization#configure-whether-administrators-can-export-your-private-data
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 10.0 (feature level 312). Previously,
|
||||||
|
there was not event available to administrators with these data.
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
$ref: "#/components/schemas/EventIdSchema"
|
||||||
|
type:
|
||||||
|
allOf:
|
||||||
|
- $ref: "#/components/schemas/EventTypeSchema"
|
||||||
|
- enum:
|
||||||
|
- realm_export_consent
|
||||||
|
user_id:
|
||||||
|
type: integer
|
||||||
|
description: |
|
||||||
|
The ID of the user whose setting was changed.
|
||||||
|
consented:
|
||||||
|
type: boolean
|
||||||
|
description: |
|
||||||
|
Whether the user has consented for their private data export.
|
||||||
|
example:
|
||||||
|
{
|
||||||
|
"type": "realm_export_consent",
|
||||||
|
"user_id": 1,
|
||||||
|
"consented": true,
|
||||||
|
}
|
||||||
- type: object
|
- type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: |
|
description: |
|
||||||
|
|
|
@ -166,6 +166,7 @@ from zerver.lib.event_schema import (
|
||||||
check_realm_domains_remove,
|
check_realm_domains_remove,
|
||||||
check_realm_emoji_update,
|
check_realm_emoji_update,
|
||||||
check_realm_export,
|
check_realm_export,
|
||||||
|
check_realm_export_consent,
|
||||||
check_realm_linkifiers,
|
check_realm_linkifiers,
|
||||||
check_realm_playgrounds,
|
check_realm_playgrounds,
|
||||||
check_realm_update,
|
check_realm_update,
|
||||||
|
@ -3285,6 +3286,17 @@ class NormalActionsTest(BaseAction):
|
||||||
check_realm_user_update("events[0]", events[0], "is_active")
|
check_realm_user_update("events[0]", events[0], "is_active")
|
||||||
check_user_group_add_members("events[1]", events[1])
|
check_user_group_add_members("events[1]", events[1])
|
||||||
|
|
||||||
|
# Verify that admins receive 'realm_export_consent' event
|
||||||
|
# when a user is reactivated.
|
||||||
|
do_deactivate_user(user_profile, acting_user=None)
|
||||||
|
self.user_profile = self.example_user("iago")
|
||||||
|
with self.verify_action(num_events=4) as events:
|
||||||
|
do_reactivate_user(user_profile, acting_user=None)
|
||||||
|
check_realm_user_update("events[0]", events[0], "is_active")
|
||||||
|
check_realm_export_consent("events[1]", events[1])
|
||||||
|
check_subscription_peer_add("events[2]", events[2])
|
||||||
|
check_user_group_add_members("events[3]", events[3])
|
||||||
|
|
||||||
def test_do_deactivate_realm(self) -> None:
|
def test_do_deactivate_realm(self) -> None:
|
||||||
realm = self.user_profile.realm
|
realm = self.user_profile.realm
|
||||||
|
|
||||||
|
@ -4248,6 +4260,39 @@ class UserDisplayActionTest(BaseAction):
|
||||||
if prop not in UserProfile.notification_setting_types:
|
if prop not in UserProfile.notification_setting_types:
|
||||||
self.do_change_user_settings_test(prop)
|
self.do_change_user_settings_test(prop)
|
||||||
|
|
||||||
|
def test_set_allow_private_data_export(self) -> None:
|
||||||
|
# Verify that both 'user_settings' and 'realm_export_consent' events
|
||||||
|
# are received by admins when they change the setting.
|
||||||
|
do_change_user_role(
|
||||||
|
self.user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None
|
||||||
|
)
|
||||||
|
self.assertFalse(self.user_profile.allow_private_data_export)
|
||||||
|
|
||||||
|
num_events = 2
|
||||||
|
with self.verify_action(num_events=num_events) as events:
|
||||||
|
do_change_user_setting(
|
||||||
|
self.user_profile,
|
||||||
|
"allow_private_data_export",
|
||||||
|
True,
|
||||||
|
acting_user=self.user_profile,
|
||||||
|
)
|
||||||
|
check_user_settings_update("events[0]", events[0])
|
||||||
|
check_realm_export_consent("events[1]", events[1])
|
||||||
|
|
||||||
|
# Verify that only 'realm_export_consent' event is received
|
||||||
|
# by admins when an another user changes their setting.
|
||||||
|
cordelia = self.example_user("cordelia")
|
||||||
|
self.assertFalse(cordelia.allow_private_data_export)
|
||||||
|
num_events = 1
|
||||||
|
with self.verify_action(num_events=num_events, state_change_expected=False) as events:
|
||||||
|
do_change_user_setting(
|
||||||
|
cordelia,
|
||||||
|
"allow_private_data_export",
|
||||||
|
True,
|
||||||
|
acting_user=cordelia,
|
||||||
|
)
|
||||||
|
check_realm_export_consent("events[0]", events[0])
|
||||||
|
|
||||||
def test_set_user_timezone(self) -> None:
|
def test_set_user_timezone(self) -> None:
|
||||||
values = ["America/Denver", "Pacific/Pago_Pago", "Pacific/Galapagos", ""]
|
values = ["America/Denver", "Pacific/Pago_Pago", "Pacific/Galapagos", ""]
|
||||||
num_events = 3
|
num_events = 3
|
||||||
|
|
Loading…
Reference in New Issue