mirror of
https://github.com/zulip/zulip.git
synced 2025-11-01 20:44:04 +00:00
channel_folders: Add API endpoint to get all channel folders.
Fixes part of #31972.
This commit is contained in:
@@ -64,6 +64,7 @@
|
||||
* [Add a default channel](/api/add-default-stream)
|
||||
* [Remove a default channel](/api/remove-default-stream)
|
||||
* [Create a channel folder](/api/create-channel-folder)
|
||||
* [Get channel folders](/api/get-channel-folders)
|
||||
|
||||
#### Users
|
||||
|
||||
|
||||
2
api_docs/unmerged.d/ZF-2a4adb.md
Normal file
2
api_docs/unmerged.d/ZF-2a4adb.md
Normal file
@@ -0,0 +1,2 @@
|
||||
* [`GET /channel_folders`](/api/get-channel-folders): Added a new endpoint
|
||||
to get all channel folders in the realm.
|
||||
@@ -54,7 +54,12 @@ def get_channel_folder_dict(channel_folder: ChannelFolder) -> ChannelFolderDict:
|
||||
)
|
||||
|
||||
|
||||
def get_channel_folders_in_realm(realm: Realm) -> list[ChannelFolderDict]:
|
||||
def get_channel_folders_in_realm(
|
||||
realm: Realm, include_archived: bool = False
|
||||
) -> list[ChannelFolderDict]:
|
||||
folders = ChannelFolder.objects.filter(realm=realm)
|
||||
if not include_archived:
|
||||
folders = folders.exclude(is_archived=True)
|
||||
|
||||
channel_folders = [get_channel_folder_dict(channel_folder) for channel_folder in folders]
|
||||
return sorted(channel_folders, key=lambda folder: folder["id"])
|
||||
|
||||
@@ -768,7 +768,7 @@ def fetch_initial_state_data(
|
||||
if want("channel_folders") and user_profile is not None:
|
||||
# TODO: Spectators should get the channel folders that
|
||||
# contain atleast one web-public channel.
|
||||
state["channel_folders"] = get_channel_folders_in_realm(user_profile.realm)
|
||||
state["channel_folders"] = get_channel_folders_in_realm(user_profile.realm, True)
|
||||
|
||||
if want("update_message_flags") and want("message"):
|
||||
# Keeping unread_msgs updated requires both message flag updates and
|
||||
|
||||
@@ -22936,6 +22936,76 @@ paths:
|
||||
description: |
|
||||
Error when the user does not have permission
|
||||
to create a channel folder:
|
||||
/channel_folders:
|
||||
get:
|
||||
operationId: get-channel-folders
|
||||
summary: Get channel folders
|
||||
tags: ["channels"]
|
||||
description: |
|
||||
Fetches all of the channel folders in the organization.
|
||||
|
||||
**Changes**: New in Zulip 11.0 (feature level ZF-2a4adb).
|
||||
requestBody:
|
||||
required: false
|
||||
content:
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
include_archived:
|
||||
description: |
|
||||
Whether to include archived channel folders in the response.
|
||||
type: boolean
|
||||
example: true
|
||||
default: false
|
||||
encoding:
|
||||
include_archived:
|
||||
contentType: application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Success.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/JsonSuccessBase"
|
||||
- additionalProperties: false
|
||||
properties:
|
||||
result: {}
|
||||
msg: {}
|
||||
ignored_parameters_unsupported: {}
|
||||
channel_folders:
|
||||
type: array
|
||||
description: |
|
||||
A list of channel folder objects.
|
||||
items:
|
||||
$ref: "#/components/schemas/ChannelFolder"
|
||||
example:
|
||||
{
|
||||
"msg": "",
|
||||
"result": "success",
|
||||
"channel_folders":
|
||||
[
|
||||
{
|
||||
"description": "Channels for frontend discussions",
|
||||
"rendered_description": "<p>Channels for frontend discussions</p>",
|
||||
"id": 1,
|
||||
"creator_id": 1,
|
||||
"date_created": 1691057093,
|
||||
"name": "Frontend",
|
||||
"is_archived": false,
|
||||
},
|
||||
{
|
||||
"description": "Channels for **backend** discussions",
|
||||
"rendered_description": "<p>Channels for <strong>backend</strong> discussions</p>",
|
||||
"id": 2,
|
||||
"creator_id": 1,
|
||||
"date_created": 1791057093,
|
||||
"name": "Backend",
|
||||
"is_archived": false,
|
||||
},
|
||||
],
|
||||
}
|
||||
/real-time:
|
||||
# This entry is a hack; it exists to give us a place to put the text
|
||||
# documenting the parameters for call_on_each_event and friends.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from typing import Any
|
||||
|
||||
import orjson
|
||||
|
||||
from zerver.actions.channel_folders import check_add_channel_folder
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.models import ChannelFolder
|
||||
from zerver.models.realms import get_realm
|
||||
@@ -70,3 +73,94 @@ class ChannelFolderCreationTest(ZulipTestCase):
|
||||
params = {"name": invalid_name, "description": "Channels for frontend discussions"}
|
||||
result = self.client_post("/json/channel_folders/create", params)
|
||||
self.assert_json_error(result, "Invalid character in channel folder name, at position 4.")
|
||||
|
||||
|
||||
class GetChannelFoldersTest(ZulipTestCase):
|
||||
def test_get_channel_folders(self) -> None:
|
||||
iago = self.example_user("iago")
|
||||
desdemona = self.example_user("desdemona")
|
||||
frontend_folder = check_add_channel_folder(
|
||||
"Frontend", "Channels for frontend discussions", acting_user=iago
|
||||
)
|
||||
backend_folder = check_add_channel_folder(
|
||||
"Backend", "Channels for **backend** discussions", acting_user=iago
|
||||
)
|
||||
marketing_folder = check_add_channel_folder(
|
||||
"Marketing", "Channels for marketing discussions", acting_user=desdemona
|
||||
)
|
||||
|
||||
lear_user = self.lear_user("cordelia")
|
||||
check_add_channel_folder("Devops", "Channels for devops discussions", acting_user=lear_user)
|
||||
|
||||
def check_channel_folders_in_zulip_realm(
|
||||
channel_folders: list[dict[str, Any]], marketing_folder_included: bool = True
|
||||
) -> None:
|
||||
if marketing_folder_included:
|
||||
self.assert_length(channel_folders, 3)
|
||||
else:
|
||||
self.assert_length(channel_folders, 2)
|
||||
|
||||
self.assertEqual(channel_folders[0]["id"], frontend_folder.id)
|
||||
self.assertEqual(channel_folders[0]["name"], "Frontend")
|
||||
self.assertEqual(channel_folders[0]["description"], "Channels for frontend discussions")
|
||||
self.assertEqual(
|
||||
channel_folders[0]["rendered_description"],
|
||||
"<p>Channels for frontend discussions</p>",
|
||||
)
|
||||
self.assertEqual(channel_folders[0]["is_archived"], frontend_folder.is_archived)
|
||||
self.assertEqual(channel_folders[0]["creator_id"], iago.id)
|
||||
|
||||
self.assertEqual(channel_folders[1]["id"], backend_folder.id)
|
||||
self.assertEqual(channel_folders[1]["name"], "Backend")
|
||||
self.assertEqual(
|
||||
channel_folders[1]["description"], "Channels for **backend** discussions"
|
||||
)
|
||||
self.assertEqual(
|
||||
channel_folders[1]["rendered_description"],
|
||||
"<p>Channels for <strong>backend</strong> discussions</p>",
|
||||
)
|
||||
self.assertEqual(channel_folders[1]["is_archived"], backend_folder.is_archived)
|
||||
self.assertEqual(channel_folders[1]["creator_id"], iago.id)
|
||||
|
||||
if marketing_folder_included:
|
||||
self.assertEqual(channel_folders[2]["id"], marketing_folder.id)
|
||||
self.assertEqual(channel_folders[2]["name"], "Marketing")
|
||||
self.assertEqual(
|
||||
channel_folders[2]["description"], "Channels for marketing discussions"
|
||||
)
|
||||
self.assertEqual(
|
||||
channel_folders[2]["rendered_description"],
|
||||
"<p>Channels for marketing discussions</p>",
|
||||
)
|
||||
self.assertEqual(channel_folders[2]["is_archived"], marketing_folder.is_archived)
|
||||
self.assertEqual(channel_folders[2]["creator_id"], desdemona.id)
|
||||
|
||||
self.login("iago")
|
||||
result = self.client_get("/json/channel_folders")
|
||||
channel_folders_data = orjson.loads(result.content)["channel_folders"]
|
||||
check_channel_folders_in_zulip_realm(channel_folders_data)
|
||||
|
||||
# Check member user can also see all channel folders.
|
||||
self.login("hamlet")
|
||||
result = self.client_get("/json/channel_folders")
|
||||
channel_folders_data = orjson.loads(result.content)["channel_folders"]
|
||||
check_channel_folders_in_zulip_realm(channel_folders_data)
|
||||
|
||||
# Check guest can also see all channel folders.
|
||||
self.login("polonius")
|
||||
result = self.client_get("/json/channel_folders")
|
||||
channel_folders_data = orjson.loads(result.content)["channel_folders"]
|
||||
check_channel_folders_in_zulip_realm(channel_folders_data)
|
||||
|
||||
marketing_folder.is_archived = True
|
||||
marketing_folder.save()
|
||||
|
||||
result = self.client_get("/json/channel_folders")
|
||||
channel_folders_data = orjson.loads(result.content)["channel_folders"]
|
||||
check_channel_folders_in_zulip_realm(channel_folders_data, False)
|
||||
|
||||
result = self.client_get(
|
||||
"/json/channel_folders", {"include_archived": orjson.dumps(True).decode()}
|
||||
)
|
||||
channel_folders_data = orjson.loads(result.content)["channel_folders"]
|
||||
check_channel_folders_in_zulip_realm(channel_folders_data)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from typing import Annotated
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from pydantic import StringConstraints
|
||||
from pydantic import Json, StringConstraints
|
||||
|
||||
from zerver.actions.channel_folders import check_add_channel_folder
|
||||
from zerver.decorator import require_realm_admin
|
||||
from zerver.lib.channel_folders import check_channel_folder_name
|
||||
from zerver.lib.channel_folders import check_channel_folder_name, get_channel_folders_in_realm
|
||||
from zerver.lib.response import json_success
|
||||
from zerver.lib.typed_endpoint import typed_endpoint
|
||||
from zerver.models.channel_folders import ChannelFolder
|
||||
@@ -25,3 +25,14 @@ def create_channel_folder(
|
||||
channel_folder = check_add_channel_folder(name, description, acting_user=user_profile)
|
||||
|
||||
return json_success(request, data={"channel_folder_id": channel_folder.id})
|
||||
|
||||
|
||||
@typed_endpoint
|
||||
def get_channel_folders(
|
||||
request: HttpRequest,
|
||||
user_profile: UserProfile,
|
||||
*,
|
||||
include_archived: Json[bool] = False,
|
||||
) -> HttpResponse:
|
||||
channel_folders = get_channel_folders_in_realm(user_profile.realm, include_archived)
|
||||
return json_success(request, data={"channel_folders": channel_folders})
|
||||
|
||||
@@ -45,7 +45,7 @@ from zerver.views.auth import (
|
||||
start_social_login,
|
||||
start_social_signup,
|
||||
)
|
||||
from zerver.views.channel_folders import create_channel_folder
|
||||
from zerver.views.channel_folders import create_channel_folder, get_channel_folders
|
||||
from zerver.views.compatibility import check_global_compatibility
|
||||
from zerver.views.custom_profile_fields import (
|
||||
create_realm_custom_profile_field,
|
||||
@@ -532,6 +532,7 @@ v1_api_and_json_patterns = [
|
||||
DELETE=remove_subscriptions_backend,
|
||||
),
|
||||
rest_path("channel_folders/create", POST=create_channel_folder),
|
||||
rest_path("channel_folders", GET=get_channel_folders),
|
||||
# topic-muting -> zerver.views.user_topics
|
||||
# (deprecated and will be removed once clients are migrated to use '/user_topics')
|
||||
rest_path("users/me/subscriptions/muted_topics", PATCH=update_muted_topic),
|
||||
|
||||
Reference in New Issue
Block a user