mirror of https://github.com/zulip/zulip.git
realm_export: Add a new endpoint to fetch private data export consents.
This commit adds a new endpoint `export/realm/consents` to fetch the consents of users for their private data exports. Fixes part of #31201.
This commit is contained in:
parent
ffbf2aaaff
commit
86194efe7b
|
@ -20,6 +20,12 @@ format used by the Zulip server that they are interacting with.
|
|||
|
||||
## Changes in Zulip 10.0
|
||||
|
||||
**Feature level 295**
|
||||
|
||||
* [`GET /export/realm/consents`](/api/get-realm-export-consents): Added
|
||||
a new endpoint to fetch the consents of users for their [private data
|
||||
exports](/help/export-your-organization#full-export-with-member-consent).
|
||||
|
||||
**Feature level 294**
|
||||
|
||||
* [`POST /register`](/api/register-queue): Clients that do not
|
||||
|
|
|
@ -118,6 +118,7 @@
|
|||
* [Update realm-level defaults of user settings](/api/update-realm-user-settings-defaults)
|
||||
* [Get all public data exports](/api/get-realm-exports)
|
||||
* [Create a public data export](/api/export-realm)
|
||||
* [Get data export consent state](/api/get-realm-export-consents)
|
||||
|
||||
#### Real-time events
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
|||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||
|
||||
API_FEATURE_LEVEL = 294 # Last bumped for `include_daectivated_groups` client capability.
|
||||
API_FEATURE_LEVEL = 295 # Last bumped for `/export/realm/consents` endpoint.
|
||||
|
||||
# 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
|
||||
|
|
|
@ -694,6 +694,16 @@ def export_realm(client: Client) -> None:
|
|||
validate_against_openapi_schema(result, "/export/realm", "post", "200")
|
||||
|
||||
|
||||
@openapi_test_function("/export/realm/consents:get")
|
||||
def get_realm_export_consents(client: Client) -> None:
|
||||
# {code_example|start}
|
||||
# Get the consents of users for their private data exports.
|
||||
result = client.call_endpoint(url="/export/realm/consents", method="GET")
|
||||
# {code_example|end}
|
||||
assert_success_response(result)
|
||||
validate_against_openapi_schema(result, "/export/realm/consents", "get", "200")
|
||||
|
||||
|
||||
@openapi_test_function("/users/me:get")
|
||||
def get_profile(client: Client) -> None:
|
||||
# {code_example|start}
|
||||
|
@ -1822,6 +1832,7 @@ def test_server_organizations(client: Client) -> None:
|
|||
create_realm_profile_field(client)
|
||||
export_realm(client)
|
||||
get_realm_exports(client)
|
||||
get_realm_export_consents(client)
|
||||
|
||||
|
||||
def test_errors(client: Client) -> None:
|
||||
|
|
|
@ -12763,6 +12763,57 @@ paths:
|
|||
description: |
|
||||
An example JSON error response for when the public data export
|
||||
exceeds the maximum allowed data export size.
|
||||
/export/realm/consents:
|
||||
get:
|
||||
operationId: get-realm-export-consents
|
||||
summary: Get data export consent state
|
||||
tags: ["server_and_organizations"]
|
||||
x-requires-administrator: true
|
||||
description: |
|
||||
Fetches which users have [consented](/help/export-your-organization#full-export-with-member-consent)
|
||||
for their private data to be exported by organization administrators.
|
||||
|
||||
**Changes**: New in Zulip 10.0 (feature level 295).
|
||||
responses:
|
||||
"200":
|
||||
description: Success.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/JsonSuccessBase"
|
||||
- additionalProperties: false
|
||||
properties:
|
||||
result: {}
|
||||
msg: {}
|
||||
ignored_parameters_unsupported: {}
|
||||
export_consents:
|
||||
type: array
|
||||
description: |
|
||||
An array of objects where each object contains a user ID and
|
||||
whether the user has consented for their private data to be exported.
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
user_id:
|
||||
description: |
|
||||
The user ID.
|
||||
type: integer
|
||||
consented:
|
||||
description: |
|
||||
Whether the user has consented for their private data export.
|
||||
type: boolean
|
||||
example:
|
||||
{
|
||||
"export_consents":
|
||||
[
|
||||
{"user_id": 11, "consented": true},
|
||||
{"user_id": 6, "consented": false},
|
||||
],
|
||||
"msg": "",
|
||||
"result": "success",
|
||||
}
|
||||
/invites:
|
||||
get:
|
||||
operationId: get-invites
|
||||
|
|
|
@ -6,6 +6,7 @@ from django.conf import settings
|
|||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
from analytics.models import RealmCount
|
||||
from zerver.actions.user_settings import do_change_user_setting
|
||||
from zerver.lib.exceptions import JsonableError
|
||||
from zerver.lib.queue import queue_json_publish
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
|
@ -16,7 +17,7 @@ from zerver.lib.test_helpers import (
|
|||
stdout_suppressed,
|
||||
use_s3_backend,
|
||||
)
|
||||
from zerver.models import Realm, RealmAuditLog
|
||||
from zerver.models import Realm, RealmAuditLog, UserProfile
|
||||
from zerver.models.realm_audit_logs import AuditLogEventType
|
||||
from zerver.views.realm_export import export_realm
|
||||
|
||||
|
@ -323,3 +324,30 @@ class RealmExportTest(ZulipTestCase):
|
|||
result,
|
||||
f"Please request a manual export from {settings.ZULIP_ADMINISTRATOR}.",
|
||||
)
|
||||
|
||||
def test_get_users_export_consents(self) -> None:
|
||||
admin = self.example_user("iago")
|
||||
self.login_user(admin)
|
||||
|
||||
# By default, export consent is set to False.
|
||||
self.assertFalse(
|
||||
UserProfile.objects.filter(
|
||||
realm=admin.realm, is_active=True, is_bot=False, allow_private_data_export=True
|
||||
).exists()
|
||||
)
|
||||
|
||||
# Hamlet and Aaron consented to export their private data.
|
||||
hamlet = self.example_user("hamlet")
|
||||
aaron = self.example_user("aaron")
|
||||
for user in [hamlet, aaron]:
|
||||
do_change_user_setting(user, "allow_private_data_export", True, acting_user=None)
|
||||
|
||||
# Verify export consents of users.
|
||||
result = self.client_get("/json/export/realm/consents")
|
||||
response_dict = self.assert_json_success(result)
|
||||
export_consents = response_dict["export_consents"]
|
||||
for export_consent in export_consents:
|
||||
if export_consent["user_id"] in [hamlet.id, aaron.id]:
|
||||
self.assertTrue(export_consent["consented"])
|
||||
continue
|
||||
self.assertFalse(export_consent["consented"])
|
||||
|
|
|
@ -112,3 +112,14 @@ def delete_realm_export(request: HttpRequest, user: UserProfile, export_id: int)
|
|||
raise JsonableError(_("Export still in progress"))
|
||||
do_delete_realm_export(user, audit_log_entry)
|
||||
return json_success(request)
|
||||
|
||||
|
||||
@require_realm_admin
|
||||
def get_users_export_consents(request: HttpRequest, user: UserProfile) -> HttpResponse:
|
||||
rows = UserProfile.objects.filter(realm=user.realm, is_active=True, is_bot=False).values(
|
||||
"id", "allow_private_data_export"
|
||||
)
|
||||
export_consents = [
|
||||
{"user_id": row["id"], "consented": row["allow_private_data_export"]} for row in rows
|
||||
]
|
||||
return json_success(request, data={"export_consents": export_consents})
|
||||
|
|
|
@ -119,7 +119,12 @@ from zerver.views.realm_domains import (
|
|||
patch_realm_domain,
|
||||
)
|
||||
from zerver.views.realm_emoji import delete_emoji, list_emoji, upload_emoji
|
||||
from zerver.views.realm_export import delete_realm_export, export_realm, get_realm_exports
|
||||
from zerver.views.realm_export import (
|
||||
delete_realm_export,
|
||||
export_realm,
|
||||
get_realm_exports,
|
||||
get_users_export_consents,
|
||||
)
|
||||
from zerver.views.realm_icon import delete_icon_backend, get_icon_backend, upload_icon
|
||||
from zerver.views.realm_linkifiers import (
|
||||
create_linkifier,
|
||||
|
@ -504,6 +509,7 @@ v1_api_and_json_patterns = [
|
|||
# export/realm -> zerver.views.realm_export
|
||||
rest_path("export/realm", POST=export_realm, GET=get_realm_exports),
|
||||
rest_path("export/realm/<int:export_id>", DELETE=delete_realm_export),
|
||||
rest_path("export/realm/consents", GET=get_users_export_consents),
|
||||
]
|
||||
|
||||
integrations_view = IntegrationView.as_view()
|
||||
|
|
Loading…
Reference in New Issue