mirror of
https://github.com/zulip/zulip.git
synced 2026-07-09 21:21:47 +08:00
api: Fix encoding of strings in streams endpoint.
* Remove unnecessary json_validator for string parameters. * Update frontend to pass right parameter. Bump api feature level and highlight the fix for `emojiset` parameter of `settings/display` endpoint in zulip.yaml file. Fixes part of #18035.
This commit is contained in:
parent
9abe1cafbe
commit
96e035a2f0
@ -652,7 +652,7 @@ export function change_stream_name(e) {
|
|||||||
channel.patch({
|
channel.patch({
|
||||||
// Stream names might contain unsafe characters so we must encode it first.
|
// Stream names might contain unsafe characters so we must encode it first.
|
||||||
url: "/json/streams/" + stream_id,
|
url: "/json/streams/" + stream_id,
|
||||||
data: {new_name: JSON.stringify(new_name)},
|
data: {new_name},
|
||||||
success() {
|
success() {
|
||||||
new_name_box.val("");
|
new_name_box.val("");
|
||||||
ui_report.success(
|
ui_report.success(
|
||||||
@ -705,7 +705,7 @@ export function change_stream_description(e) {
|
|||||||
// Description might contain unsafe characters so we must encode it first.
|
// Description might contain unsafe characters so we must encode it first.
|
||||||
url: "/json/streams/" + stream_id,
|
url: "/json/streams/" + stream_id,
|
||||||
data: {
|
data: {
|
||||||
description: JSON.stringify(description),
|
description,
|
||||||
},
|
},
|
||||||
success() {
|
success() {
|
||||||
// The event from the server will update the rest of the UI
|
// The event from the server will update the rest of the UI
|
||||||
|
|||||||
@ -10,6 +10,13 @@ below features are supported.
|
|||||||
|
|
||||||
## Changes in Zulip 4.0
|
## Changes in Zulip 4.0
|
||||||
|
|
||||||
|
**Feature level 64**
|
||||||
|
|
||||||
|
* `PATCH /streams/{stream_id}`: Removed unnecessary JSON-encoding of string
|
||||||
|
parameters `new_name` and `description`.
|
||||||
|
* `PATCH /settings/display`: Removed unnecessary JSON-encoding of string
|
||||||
|
parameters `default_view`, `emojiset` and `timezone`.
|
||||||
|
|
||||||
**Feature level 63**
|
**Feature level 63**
|
||||||
|
|
||||||
* `PATCH /settings/notifications`: Removed unnecessary JSON-encoding of string
|
* `PATCH /settings/notifications`: Removed unnecessary JSON-encoding of string
|
||||||
|
|||||||
@ -30,7 +30,7 @@ DESKTOP_WARNING_VERSION = "5.2.0"
|
|||||||
#
|
#
|
||||||
# Changes should be accompanied by documentation explaining what the
|
# Changes should be accompanied by documentation explaining what the
|
||||||
# new level means in templates/zerver/api/changelog.md.
|
# new level means in templates/zerver/api/changelog.md.
|
||||||
API_FEATURE_LEVEL = 63
|
API_FEATURE_LEVEL = 64
|
||||||
|
|
||||||
# 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
|
||||||
|
|||||||
@ -9323,11 +9323,11 @@ paths:
|
|||||||
in: query
|
in: query
|
||||||
description: |
|
description: |
|
||||||
Notification sound name.
|
Notification sound name.
|
||||||
content:
|
|
||||||
application/json:
|
**Changes**: Removed unnecessary JSON-encoding of parameter in Zulip 4.0 (feature level 63).
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: ding
|
example: ding
|
||||||
- name: enable_desktop_notifications
|
- name: enable_desktop_notifications
|
||||||
in: query
|
in: query
|
||||||
description: |
|
description: |
|
||||||
@ -9598,12 +9598,12 @@ paths:
|
|||||||
This controls both the Zulip UI as well as email notifications sent to the user.
|
This controls both the Zulip UI as well as email notifications sent to the user.
|
||||||
|
|
||||||
The value needs to be a standard language code that the Zulip server has
|
The value needs to be a standard language code that the Zulip server has
|
||||||
translation data for; for example, `"en"` for English` or `"de"` for German.
|
translation data for; for example, `"en"` for English or `"de"` for German.
|
||||||
content:
|
|
||||||
application/json:
|
**Changes**: Removed unnecessary JSON-encoding of parameter in Zulip 4.0 (feature level 63).
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: "en"
|
example: en
|
||||||
- name: default_view
|
- name: default_view
|
||||||
in: query
|
in: query
|
||||||
description: |
|
description: |
|
||||||
@ -9612,9 +9612,11 @@ paths:
|
|||||||
|
|
||||||
* "recent_topics" - Recent topics view
|
* "recent_topics" - Recent topics view
|
||||||
* "all_messages" - All messages view
|
* "all_messages" - All messages view
|
||||||
|
|
||||||
|
**Changes**: Removed unnecessary JSON-encoding of parameter in Zulip 4.0 (feature level 64).
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: '"all_messages"'
|
example: all_messages
|
||||||
- name: left_side_userlist
|
- name: left_side_userlist
|
||||||
in: query
|
in: query
|
||||||
description: |
|
description: |
|
||||||
@ -9634,6 +9636,8 @@ paths:
|
|||||||
* "google-blob" - Google classic
|
* "google-blob" - Google classic
|
||||||
* "twitter" - Twitter
|
* "twitter" - Twitter
|
||||||
* "text" - Plain text
|
* "text" - Plain text
|
||||||
|
|
||||||
|
**Changes**: Removed unnecessary JSON-encoding of parameter in Zulip 4.0 (feature level 64).
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: "google"
|
example: "google"
|
||||||
@ -9661,11 +9665,11 @@ paths:
|
|||||||
|
|
||||||
Timezone values supported by the server are served at
|
Timezone values supported by the server are served at
|
||||||
[/static/generated/timezones.json](/static/generated/timezones.json).
|
[/static/generated/timezones.json](/static/generated/timezones.json).
|
||||||
content:
|
|
||||||
application/json:
|
**Changes**: Removed unnecessary JSON-encoding of parameter in Zulip 4.0 (feature level 64).
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: "Asia/Kolkata"
|
example: "Asia/Kolkata"
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Success
|
description: Success
|
||||||
@ -9950,22 +9954,25 @@ paths:
|
|||||||
- name: description
|
- name: description
|
||||||
in: query
|
in: query
|
||||||
description: |
|
description: |
|
||||||
The new description for the stream.
|
The new description for the stream. Limited Zulip markdown is allowed in this
|
||||||
content:
|
field.
|
||||||
application/json:
|
|
||||||
schema:
|
**Changes**: Removed unnecessary JSON-encoding of this parameter in
|
||||||
type: string
|
Zulip 4.0 (feature level 64).
|
||||||
example: This stream is related to football dicsussions.
|
schema:
|
||||||
|
type: string
|
||||||
|
example: "Discuss Italian history and travel destinations."
|
||||||
required: false
|
required: false
|
||||||
- name: new_name
|
- name: new_name
|
||||||
in: query
|
in: query
|
||||||
description: |
|
description: |
|
||||||
The new name for the stream.
|
The new name for the stream.
|
||||||
content:
|
|
||||||
application/json:
|
**Changes**: Removed unnecessary JSON-encoding of this parameter in
|
||||||
schema:
|
Zulip 4.0 (feature level 64).
|
||||||
type: string
|
schema:
|
||||||
example: Italy
|
type: string
|
||||||
|
example: Italy
|
||||||
required: false
|
required: false
|
||||||
- name: is_private
|
- name: is_private
|
||||||
in: query
|
in: query
|
||||||
|
|||||||
@ -759,31 +759,21 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
stream = self.subscribe(user_profile, "stream_name1")
|
stream = self.subscribe(user_profile, "stream_name1")
|
||||||
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
|
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
|
||||||
|
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream.id}", {"new_name": "stream_name1"})
|
||||||
f"/json/streams/{stream.id}", {"new_name": orjson.dumps("stream_name1").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_error(result, "Stream already has that name!")
|
self.assert_json_error(result, "Stream already has that name!")
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream.id}", {"new_name": "Denmark"})
|
||||||
f"/json/streams/{stream.id}", {"new_name": orjson.dumps("Denmark").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_error(result, "Stream name 'Denmark' is already taken.")
|
self.assert_json_error(result, "Stream name 'Denmark' is already taken.")
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream.id}", {"new_name": "denmark "})
|
||||||
f"/json/streams/{stream.id}", {"new_name": orjson.dumps("denmark ").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_error(result, "Stream name 'denmark' is already taken.")
|
self.assert_json_error(result, "Stream name 'denmark' is already taken.")
|
||||||
|
|
||||||
# Do a rename that is case-only--this should succeed.
|
# Do a rename that is case-only--this should succeed.
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream.id}", {"new_name": "sTREAm_name1"})
|
||||||
f"/json/streams/{stream.id}", {"new_name": orjson.dumps("sTREAm_name1").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
|
||||||
events: List[Mapping[str, Any]] = []
|
events: List[Mapping[str, Any]] = []
|
||||||
with tornado_redirected_to_list(events):
|
with tornado_redirected_to_list(events):
|
||||||
stream_id = get_stream("stream_name1", user_profile.realm).id
|
stream_id = get_stream("stream_name1", user_profile.realm).id
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream_id}", {"new_name": "stream_name2"})
|
||||||
f"/json/streams/{stream_id}", {"new_name": orjson.dumps("stream_name2").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
event = events[1]["event"]
|
event = events[1]["event"]
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -813,9 +803,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
# *NOTE: Here encoding is needed when Unicode string is passed as an argument*
|
# *NOTE: Here encoding is needed when Unicode string is passed as an argument*
|
||||||
with tornado_redirected_to_list(events):
|
with tornado_redirected_to_list(events):
|
||||||
stream_id = stream_name2_exists.id
|
stream_id = stream_name2_exists.id
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream_id}", {"new_name": "नया नाम"})
|
||||||
f"/json/streams/{stream_id}", {"new_name": orjson.dumps("नया नाम").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
# While querying, system can handle Unicode strings.
|
# While querying, system can handle Unicode strings.
|
||||||
stream_name_uni_exists = get_stream("नया नाम", realm)
|
stream_name_uni_exists = get_stream("नया नाम", realm)
|
||||||
@ -828,7 +816,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
stream_id = stream_name_uni_exists.id
|
stream_id = stream_name_uni_exists.id
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
f"/json/streams/{stream_id}",
|
f"/json/streams/{stream_id}",
|
||||||
{"new_name": orjson.dumps("नाम में क्या रक्खा हे").decode()},
|
{"new_name": "नाम में क्या रक्खा हे"},
|
||||||
)
|
)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
# While querying, system can handle Unicode strings.
|
# While querying, system can handle Unicode strings.
|
||||||
@ -840,9 +828,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
# Test case to change name from one language to other.
|
# Test case to change name from one language to other.
|
||||||
with tornado_redirected_to_list(events):
|
with tornado_redirected_to_list(events):
|
||||||
stream_id = stream_name_new_uni_exists.id
|
stream_id = stream_name_new_uni_exists.id
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream_id}", {"new_name": "français"})
|
||||||
f"/json/streams/{stream_id}", {"new_name": orjson.dumps("français").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
stream_name_fr_exists = get_stream("français", realm)
|
stream_name_fr_exists = get_stream("français", realm)
|
||||||
self.assertTrue(stream_name_fr_exists)
|
self.assertTrue(stream_name_fr_exists)
|
||||||
@ -850,9 +836,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
# Test case to change name to mixed language name.
|
# Test case to change name to mixed language name.
|
||||||
with tornado_redirected_to_list(events):
|
with tornado_redirected_to_list(events):
|
||||||
stream_id = stream_name_fr_exists.id
|
stream_id = stream_name_fr_exists.id
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream_id}", {"new_name": "français name"})
|
||||||
f"/json/streams/{stream_id}", {"new_name": orjson.dumps("français name").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
stream_name_mixed_exists = get_stream("français name", realm)
|
stream_name_mixed_exists = get_stream("français name", realm)
|
||||||
self.assertTrue(stream_name_mixed_exists)
|
self.assertTrue(stream_name_mixed_exists)
|
||||||
@ -867,7 +851,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
stream_id = get_stream("stream_private_name1", realm).id
|
stream_id = get_stream("stream_private_name1", realm).id
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
f"/json/streams/{stream_id}",
|
f"/json/streams/{stream_id}",
|
||||||
{"new_name": orjson.dumps("stream_private_name2").decode()},
|
{"new_name": "stream_private_name2"},
|
||||||
)
|
)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
notified_user_ids = set(events[1]["users"])
|
notified_user_ids = set(events[1]["users"])
|
||||||
@ -896,7 +880,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
with tornado_redirected_to_list(events):
|
with tornado_redirected_to_list(events):
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
f"/json/streams/{new_stream.id}",
|
f"/json/streams/{new_stream.id}",
|
||||||
{"new_name": orjson.dumps("stream_rename").decode()},
|
{"new_name": "stream_rename"},
|
||||||
)
|
)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
self.assertEqual(len(events), 3)
|
self.assertEqual(len(events), 3)
|
||||||
@ -914,9 +898,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
self.assertFalse(sub.is_stream_admin)
|
self.assertFalse(sub.is_stream_admin)
|
||||||
|
|
||||||
stream_id = get_stream("stream_name1", user_profile.realm).id
|
stream_id = get_stream("stream_name1", user_profile.realm).id
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream_id}", {"new_name": "stream_name2"})
|
||||||
f"/json/streams/{stream_id}", {"new_name": orjson.dumps("stream_name2").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_error(result, "Must be an organization or stream administrator")
|
self.assert_json_error(result, "Must be an organization or stream administrator")
|
||||||
|
|
||||||
def test_notify_on_stream_rename(self) -> None:
|
def test_notify_on_stream_rename(self) -> None:
|
||||||
@ -926,9 +908,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
|
|
||||||
stream = self.subscribe(user_profile, "stream_name1")
|
stream = self.subscribe(user_profile, "stream_name1")
|
||||||
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
|
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream.id}", {"new_name": "stream_name2"})
|
||||||
f"/json/streams/{stream.id}", {"new_name": orjson.dumps("stream_name2").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
|
||||||
# Inspect the notification message sent
|
# Inspect the notification message sent
|
||||||
@ -956,9 +936,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
|
||||||
stream_id = get_stream("private_stream", iago.realm).id
|
stream_id = get_stream("private_stream", iago.realm).id
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream_id}", {"new_name": "new_private_stream"})
|
||||||
f"/json/streams/{stream_id}", {"new_name": orjson.dumps("new_private_stream").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
@ -992,9 +970,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||||||
|
|
||||||
stream_id = get_stream("private_stream_1", hamlet.realm).id
|
stream_id = get_stream("private_stream_1", hamlet.realm).id
|
||||||
|
|
||||||
result = self.client_patch(
|
result = self.client_patch(f"/json/streams/{stream_id}", {"new_name": "private_stream_2"})
|
||||||
f"/json/streams/{stream_id}", {"new_name": orjson.dumps("private_stream_2").decode()}
|
|
||||||
)
|
|
||||||
self.assert_json_error(result, "Invalid stream id")
|
self.assert_json_error(result, "Invalid stream id")
|
||||||
|
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
|
|||||||
@ -244,7 +244,7 @@ def update_stream_backend(
|
|||||||
user_profile: UserProfile,
|
user_profile: UserProfile,
|
||||||
stream_id: int,
|
stream_id: int,
|
||||||
description: Optional[str] = REQ(
|
description: Optional[str] = REQ(
|
||||||
json_validator=check_capped_string(Stream.MAX_DESCRIPTION_LENGTH), default=None
|
str_validator=check_capped_string(Stream.MAX_DESCRIPTION_LENGTH), default=None
|
||||||
),
|
),
|
||||||
is_private: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
is_private: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
is_announcement_only: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
is_announcement_only: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
@ -252,7 +252,7 @@ def update_stream_backend(
|
|||||||
json_validator=check_int_in(Stream.STREAM_POST_POLICY_TYPES), default=None
|
json_validator=check_int_in(Stream.STREAM_POST_POLICY_TYPES), default=None
|
||||||
),
|
),
|
||||||
history_public_to_subscribers: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
history_public_to_subscribers: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
new_name: Optional[str] = REQ(json_validator=check_string, default=None),
|
new_name: Optional[str] = REQ(default=None),
|
||||||
message_retention_days: Optional[Union[int, str]] = REQ(
|
message_retention_days: Optional[Union[int, str]] = REQ(
|
||||||
json_validator=check_string_or_int, default=None
|
json_validator=check_string_or_int, default=None
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user