mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 21:43:21 +00:00
This makes it possible for Zulip administrators to delete messages. This is primarily intended for use in deleting early test messages, but it can solve other problems as well. Later we'll want to play with the permissions model for this, but for now, the goal is just to integrate the feature. Note that it saves the deleted messages for some time using the same approach as Zulip's message retention policy feature. Fixes #135.
86 lines
3.5 KiB
Python
86 lines
3.5 KiB
Python
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
|
|
from datetime import timedelta
|
|
|
|
from django.db import connection, transaction
|
|
from django.forms.models import model_to_dict
|
|
from django.utils.timezone import now as timezone_now
|
|
from zerver.models import Realm, Message, UserMessage, ArchivedMessage, ArchivedUserMessage, \
|
|
Attachment, ArchivedAttachment
|
|
|
|
from typing import Any, Dict, Optional, Generator
|
|
|
|
|
|
def get_realm_expired_messages(realm):
|
|
# type: (Any) -> Optional[Dict[str, Any]]
|
|
expired_date = timezone_now() - timedelta(days=realm.message_retention_days)
|
|
expired_messages = Message.objects.order_by('id').filter(sender__realm=realm,
|
|
pub_date__lt=expired_date)
|
|
if not expired_messages.exists():
|
|
return None
|
|
return {'realm_id': realm.id, 'expired_messages': expired_messages}
|
|
|
|
|
|
def get_expired_messages():
|
|
# type: () -> Generator[Any, None, None]
|
|
# Get all expired messages by Realm.
|
|
realms = Realm.objects.order_by('string_id').filter(
|
|
deactivated=False, message_retention_days__isnull=False)
|
|
for realm in realms:
|
|
realm_expired_messages = get_realm_expired_messages(realm)
|
|
if realm_expired_messages:
|
|
yield realm_expired_messages
|
|
|
|
|
|
def move_attachment_message_to_archive_by_message(message_id):
|
|
# type: (int) -> None
|
|
# Move attachments messages relation table data to archive.
|
|
query = """
|
|
INSERT INTO zerver_archivedattachment_messages (id, archivedattachment_id,
|
|
archivedmessage_id)
|
|
SELECT zerver_attachment_messages.id, zerver_attachment_messages.attachment_id,
|
|
zerver_attachment_messages.message_id
|
|
FROM zerver_attachment_messages
|
|
LEFT JOIN zerver_archivedattachment_messages
|
|
ON zerver_archivedattachment_messages.id = zerver_attachment_messages.id
|
|
WHERE zerver_attachment_messages.message_id = {message_id}
|
|
AND zerver_archivedattachment_messages.id IS NULL
|
|
"""
|
|
with connection.cursor() as cursor:
|
|
cursor.execute(query.format(message_id=message_id))
|
|
|
|
|
|
@transaction.atomic
|
|
def move_message_to_archive(message_id):
|
|
# type: (int) -> None
|
|
msg = list(Message.objects.filter(id=message_id).values())
|
|
if not msg:
|
|
raise Message.DoesNotExist
|
|
arc_message = ArchivedMessage(**msg[0])
|
|
arc_message.save()
|
|
|
|
# Move user_messages to the archive.
|
|
user_messages = UserMessage.objects.filter(
|
|
message_id=message_id).exclude(id__in=ArchivedUserMessage.objects.all())
|
|
archiving_messages = []
|
|
for user_message in user_messages.values():
|
|
archiving_messages.append(ArchivedUserMessage(**user_message))
|
|
ArchivedUserMessage.objects.bulk_create(archiving_messages)
|
|
|
|
# Move attachments to archive
|
|
attachments = Attachment.objects.filter(messages__id=message_id).exclude(
|
|
id__in=ArchivedAttachment.objects.all())
|
|
archiving_attachments = []
|
|
for attachment in attachments.values():
|
|
archiving_attachments.append(ArchivedAttachment(**attachment))
|
|
ArchivedAttachment.objects.bulk_create(archiving_attachments)
|
|
move_attachment_message_to_archive_by_message(message_id)
|
|
|
|
# Remove data from main tables
|
|
Message.objects.get(id=message_id).delete()
|
|
user_messages.filter(id__in=ArchivedUserMessage.objects.all(),
|
|
message_id__isnull=True).delete()
|
|
archived_attachments = ArchivedAttachment.objects.filter(messages__id=message_id)
|
|
Attachment.objects.filter(messages__isnull=True, id__in=archived_attachments).delete()
|