mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	folders: Don't allow archiving a folder if it contains channels.
This commit is contained in:
		@@ -7,7 +7,7 @@ from zerver.lib.markdown import markdown_convert
 | 
				
			|||||||
from zerver.lib.streams import get_web_public_streams_queryset
 | 
					from zerver.lib.streams import get_web_public_streams_queryset
 | 
				
			||||||
from zerver.lib.string_validation import check_string_is_printable
 | 
					from zerver.lib.string_validation import check_string_is_printable
 | 
				
			||||||
from zerver.lib.timestamp import datetime_to_timestamp
 | 
					from zerver.lib.timestamp import datetime_to_timestamp
 | 
				
			||||||
from zerver.models import ChannelFolder, Realm, UserProfile
 | 
					from zerver.models import ChannelFolder, Realm, Stream, UserProfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChannelFolderDict(TypedDict):
 | 
					class ChannelFolderDict(TypedDict):
 | 
				
			||||||
@@ -81,3 +81,9 @@ def get_channel_folders_for_spectators(realm: Realm) -> list[ChannelFolderDict]:
 | 
				
			|||||||
    folders = ChannelFolder.objects.filter(id__in=folder_ids_for_web_public_streams)
 | 
					    folders = ChannelFolder.objects.filter(id__in=folder_ids_for_web_public_streams)
 | 
				
			||||||
    channel_folders = [get_channel_folder_dict(channel_folder) for channel_folder in folders]
 | 
					    channel_folders = [get_channel_folder_dict(channel_folder) for channel_folder in folders]
 | 
				
			||||||
    return sorted(channel_folders, key=lambda folder: folder["id"])
 | 
					    return sorted(channel_folders, key=lambda folder: folder["id"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_channel_folder_in_use(channel_folder: ChannelFolder) -> bool:
 | 
				
			||||||
 | 
					    if Stream.objects.filter(folder=channel_folder).exists():
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					    return False
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,9 +3,11 @@ from typing import Any
 | 
				
			|||||||
import orjson
 | 
					import orjson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from zerver.actions.channel_folders import check_add_channel_folder
 | 
					from zerver.actions.channel_folders import check_add_channel_folder
 | 
				
			||||||
 | 
					from zerver.actions.streams import do_change_stream_folder, do_deactivate_stream
 | 
				
			||||||
from zerver.lib.test_classes import ZulipTestCase
 | 
					from zerver.lib.test_classes import ZulipTestCase
 | 
				
			||||||
from zerver.models import ChannelFolder
 | 
					from zerver.models import ChannelFolder
 | 
				
			||||||
from zerver.models.realms import get_realm
 | 
					from zerver.models.realms import get_realm
 | 
				
			||||||
 | 
					from zerver.models.streams import get_stream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChannelFolderCreationTest(ZulipTestCase):
 | 
					class ChannelFolderCreationTest(ZulipTestCase):
 | 
				
			||||||
@@ -260,8 +262,10 @@ class UpdateChannelFoldersTest(ZulipTestCase):
 | 
				
			|||||||
        self.assertEqual(channel_folder.rendered_description, "")
 | 
					        self.assertEqual(channel_folder.rendered_description, "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_archiving_and_unarchiving_channel_folder(self) -> None:
 | 
					    def test_archiving_and_unarchiving_channel_folder(self) -> None:
 | 
				
			||||||
 | 
					        desdemona = self.example_user("desdemona")
 | 
				
			||||||
 | 
					        realm = get_realm("zulip")
 | 
				
			||||||
        channel_folder = check_add_channel_folder(
 | 
					        channel_folder = check_add_channel_folder(
 | 
				
			||||||
            get_realm("zulip"),
 | 
					            realm,
 | 
				
			||||||
            "Frontend",
 | 
					            "Frontend",
 | 
				
			||||||
            "Channels for frontend discussions",
 | 
					            "Channels for frontend discussions",
 | 
				
			||||||
            acting_user=self.example_user("desdemona"),
 | 
					            acting_user=self.example_user("desdemona"),
 | 
				
			||||||
@@ -290,3 +294,24 @@ class UpdateChannelFoldersTest(ZulipTestCase):
 | 
				
			|||||||
        self.assert_json_success(result)
 | 
					        self.assert_json_success(result)
 | 
				
			||||||
        channel_folder = ChannelFolder.objects.get(id=channel_folder_id)
 | 
					        channel_folder = ChannelFolder.objects.get(id=channel_folder_id)
 | 
				
			||||||
        self.assertFalse(channel_folder.is_archived)
 | 
					        self.assertFalse(channel_folder.is_archived)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Folder containing channels cannot be archived.
 | 
				
			||||||
 | 
					        stream = get_stream("Verona", realm)
 | 
				
			||||||
 | 
					        do_change_stream_folder(stream, channel_folder, acting_user=desdemona)
 | 
				
			||||||
 | 
					        params = {"is_archived": orjson.dumps(True).decode()}
 | 
				
			||||||
 | 
					        result = self.client_patch(f"/json/channel_folders/{channel_folder_id}", params)
 | 
				
			||||||
 | 
					        self.assert_json_error(
 | 
				
			||||||
 | 
					            result, "You need to remove all the channels from this folder to archive it."
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do_deactivate_stream(stream, acting_user=desdemona)
 | 
				
			||||||
 | 
					        result = self.client_patch(f"/json/channel_folders/{channel_folder_id}", params)
 | 
				
			||||||
 | 
					        self.assert_json_error(
 | 
				
			||||||
 | 
					            result, "You need to remove all the channels from this folder to archive it."
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do_change_stream_folder(stream, None, acting_user=desdemona)
 | 
				
			||||||
 | 
					        result = self.client_patch(f"/json/channel_folders/{channel_folder_id}", params)
 | 
				
			||||||
 | 
					        self.assert_json_success(result)
 | 
				
			||||||
 | 
					        channel_folder = ChannelFolder.objects.get(id=channel_folder_id)
 | 
				
			||||||
 | 
					        self.assertTrue(channel_folder.is_archived)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
from typing import Annotated
 | 
					from typing import Annotated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.http import HttpRequest, HttpResponse
 | 
					from django.http import HttpRequest, HttpResponse
 | 
				
			||||||
 | 
					from django.utils.translation import gettext as _
 | 
				
			||||||
from pydantic import Json, StringConstraints
 | 
					from pydantic import Json, StringConstraints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from zerver.actions.channel_folders import (
 | 
					from zerver.actions.channel_folders import (
 | 
				
			||||||
@@ -12,10 +13,12 @@ from zerver.actions.channel_folders import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
from zerver.decorator import require_realm_admin
 | 
					from zerver.decorator import require_realm_admin
 | 
				
			||||||
from zerver.lib.channel_folders import (
 | 
					from zerver.lib.channel_folders import (
 | 
				
			||||||
 | 
					    check_channel_folder_in_use,
 | 
				
			||||||
    check_channel_folder_name,
 | 
					    check_channel_folder_name,
 | 
				
			||||||
    get_channel_folder_by_id,
 | 
					    get_channel_folder_by_id,
 | 
				
			||||||
    get_channel_folders_in_realm,
 | 
					    get_channel_folders_in_realm,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					from zerver.lib.exceptions import JsonableError
 | 
				
			||||||
from zerver.lib.response import json_success
 | 
					from zerver.lib.response import json_success
 | 
				
			||||||
from zerver.lib.typed_endpoint import PathOnly, typed_endpoint
 | 
					from zerver.lib.typed_endpoint import PathOnly, typed_endpoint
 | 
				
			||||||
from zerver.models.channel_folders import ChannelFolder
 | 
					from zerver.models.channel_folders import ChannelFolder
 | 
				
			||||||
@@ -71,6 +74,11 @@ def update_channel_folder(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if is_archived is not None and channel_folder.is_archived != is_archived:
 | 
					    if is_archived is not None and channel_folder.is_archived != is_archived:
 | 
				
			||||||
        if is_archived:
 | 
					        if is_archived:
 | 
				
			||||||
 | 
					            if check_channel_folder_in_use(channel_folder):
 | 
				
			||||||
 | 
					                raise JsonableError(
 | 
				
			||||||
 | 
					                    _("You need to remove all the channels from this folder to archive it.")
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            do_archive_channel_folder(channel_folder, acting_user=user_profile)
 | 
					            do_archive_channel_folder(channel_folder, acting_user=user_profile)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            do_unarchive_channel_folder(channel_folder, acting_user=user_profile)
 | 
					            do_unarchive_channel_folder(channel_folder, acting_user=user_profile)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user