mirror of https://github.com/zulip/zulip.git
realm: Add 'PATCH /realm/user_settings_defaults' endpoint.
The realm-level default value of settngs for new users will be updated using this endpoint.
This commit is contained in:
parent
17087cf06f
commit
693d58265e
|
@ -11,6 +11,11 @@ below features are supported.
|
||||||
|
|
||||||
## Changes in Zulip 5.0
|
## Changes in Zulip 5.0
|
||||||
|
|
||||||
|
**Feature level 96**
|
||||||
|
|
||||||
|
* [`PATCH /realm/user_settings_defaults`](/api/update-realm-user-settings-defaults):
|
||||||
|
Added new endpoint to update default values of user settings in a realm.
|
||||||
|
|
||||||
**Feature level 95**
|
**Feature level 95**
|
||||||
|
|
||||||
* [`POST /register`](/api/register-queue): Added
|
* [`POST /register`](/api/register-queue): Added
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
* [Get all custom profile fields](/api/get-custom-profile-fields)
|
* [Get all custom profile fields](/api/get-custom-profile-fields)
|
||||||
* [Reorder custom profile fields](/api/reorder-custom-profile-fields)
|
* [Reorder custom profile fields](/api/reorder-custom-profile-fields)
|
||||||
* [Create a custom profile field](/api/create-custom-profile-field)
|
* [Create a custom profile field](/api/create-custom-profile-field)
|
||||||
|
* [Change default values of user preferences](/api/update-realm-user-settings-defaults)
|
||||||
|
|
||||||
#### Real-time events
|
#### Real-time events
|
||||||
|
|
||||||
|
|
|
@ -896,6 +896,7 @@ help_markdown_rules = RuleList(
|
||||||
"good_lines": ["Organization", "deactivate_realm", "realm_filter"],
|
"good_lines": ["Organization", "deactivate_realm", "realm_filter"],
|
||||||
"bad_lines": ["Users are in a realm", "Realm is the best model"],
|
"bad_lines": ["Users are in a realm", "Realm is the best model"],
|
||||||
"description": "Realms are referred to as Organizations in user-facing docs.",
|
"description": "Realms are referred to as Organizations in user-facing docs.",
|
||||||
|
"exclude_pattern": "-realm-",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
length_exclude=markdown_docs_length_exclude,
|
length_exclude=markdown_docs_length_exclude,
|
||||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3"
|
||||||
# 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, as well as
|
# new level means in templates/zerver/api/changelog.md, as well as
|
||||||
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
||||||
API_FEATURE_LEVEL = 95
|
API_FEATURE_LEVEL = 96
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -587,7 +587,7 @@ def check_string_or_int(var_name: str, val: object) -> Union[str, int]:
|
||||||
def check_settings_values(
|
def check_settings_values(
|
||||||
notification_sound: Optional[str],
|
notification_sound: Optional[str],
|
||||||
email_notifications_batching_period_seconds: Optional[int],
|
email_notifications_batching_period_seconds: Optional[int],
|
||||||
default_language: Optional[str],
|
default_language: Optional[str] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
from zerver.lib.actions import get_available_notification_sounds
|
from zerver.lib.actions import get_available_notification_sounds
|
||||||
from zerver.lib.i18n import get_available_language_codes
|
from zerver.lib.i18n import get_available_language_codes
|
||||||
|
|
|
@ -7499,6 +7499,349 @@ paths:
|
||||||
description: |
|
description: |
|
||||||
The ID for the custom profile field.
|
The ID for the custom profile field.
|
||||||
example: {"result": "success", "msg": "", "id": 9}
|
example: {"result": "success", "msg": "", "id": 9}
|
||||||
|
/realm/user_settings_defaults:
|
||||||
|
patch:
|
||||||
|
operationId: update-realm-user-settings-defaults
|
||||||
|
summary: Update realm-level defaults of user settings.
|
||||||
|
tags: ["server_and_organizations"]
|
||||||
|
x-requires-administrator: true
|
||||||
|
description: |
|
||||||
|
Change the the default/initial values of
|
||||||
|
[personal preference settings](/api/update-settings) for new users
|
||||||
|
created in the organization.
|
||||||
|
|
||||||
|
`PATCH {{ api_url }}/v1/realm/user_settings_defaults`
|
||||||
|
|
||||||
|
This feature can be invaluable for customizing Zulip's default
|
||||||
|
settings for notifications or UI to be appropriate for how the
|
||||||
|
organization is using Zulip. (Note that this only supports
|
||||||
|
personal preference settings, like when to send push
|
||||||
|
notifications or what emoji set to use, not profile or
|
||||||
|
identity settings that naturally should be different for each user).
|
||||||
|
|
||||||
|
Note that this endpoint cannot, at present, be used to modify
|
||||||
|
settings for existing users in any way.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 5.0 (feature level 96).
|
||||||
|
x-curl-examples-parameters:
|
||||||
|
oneOf:
|
||||||
|
- type: include
|
||||||
|
parameters:
|
||||||
|
enum:
|
||||||
|
- left_side_userlist
|
||||||
|
- emojiset
|
||||||
|
parameters:
|
||||||
|
- name: dense_mode
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
This setting has no effect at present. It is reserved for use in controlling
|
||||||
|
the default font size in Zulip.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: starred_message_counts
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Whether clients should display the [number of starred
|
||||||
|
messages](/help/star-a-message#display-the-number-of-starred-messages).
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: fluid_layout_width
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Whether to use the [maximum available screen width](/help/enable-full-width-display)
|
||||||
|
for the web app's center panel (message feed, recent topics) on wide screens.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: high_contrast_mode
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
This setting is reserved for use to control variations in Zulip's design
|
||||||
|
to help visually impaired users.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: color_scheme
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Controls which [color theme](/help/night-mode) to use.
|
||||||
|
|
||||||
|
* 1 - Automatic
|
||||||
|
* 2 - Night mode
|
||||||
|
* 3 - Day mode
|
||||||
|
|
||||||
|
Automatic detection is implementing using the standard `prefers-color-scheme`
|
||||||
|
media query.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
enum:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
example: 1
|
||||||
|
- name: enable_drafts_synchronization
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
A boolean parameter to control whether synchronizing drafts is enabled for
|
||||||
|
the user. When synchronization is disabled, all drafts stored in the server
|
||||||
|
will be automatically deleted from the server.
|
||||||
|
|
||||||
|
This does not do anything (like sending events) to delete local copies of
|
||||||
|
drafts stored in clients.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: translate_emoticons
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Whether to [translate emoticons to emoji](/help/enable-emoticon-translations)
|
||||||
|
in messages the user sends.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: default_view
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
The [default view](/help/change-default-view) used when opening a new
|
||||||
|
Zulip web app window or hitting the `Esc` keyboard shortcut repeatedly.
|
||||||
|
|
||||||
|
* "recent_topics" - Recent topics view
|
||||||
|
* "all_messages" - All messages view
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: all_messages
|
||||||
|
- name: left_side_userlist
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Whether the users list on left sidebar in narrow windows.
|
||||||
|
|
||||||
|
This feature is not heavily used and is likely to be reworked.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: emojiset
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
The user's configured [emoji set](/help/emoji-and-emoticons#use-emoticons),
|
||||||
|
used to display emoji to the user everything they appear in the UI.
|
||||||
|
|
||||||
|
* "google" - Google modern
|
||||||
|
* "google-blob" - Google classic
|
||||||
|
* "twitter" - Twitter
|
||||||
|
* "text" - Plain text
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: "google"
|
||||||
|
- name: demote_inactive_streams
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Whether to [demote inactive streams](/help/manage-inactive-streams) in the left sidebar.
|
||||||
|
|
||||||
|
* 1 - Automatic
|
||||||
|
* 2 - Always
|
||||||
|
* 3 - Never
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
enum:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
example: 1
|
||||||
|
- name: enable_stream_desktop_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable visual desktop notifications for stream messages.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enable_stream_email_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable email notifications for stream messages.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enable_stream_push_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable mobile notifications for stream messages.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enable_stream_audible_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable audible desktop notifications for stream messages.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: notification_sound
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Notification sound name.
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: ding
|
||||||
|
- name: enable_desktop_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable visual desktop notifications for private messages and @-mentions.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enable_sounds
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable audible desktop notifications for private messages and
|
||||||
|
@-mentions.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: email_notifications_batching_period_seconds
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
The duration (in seconds) for which the server should wait to batch
|
||||||
|
email notifications before sending them.
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
example: 120
|
||||||
|
- name: enable_offline_email_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable email notifications for private messages and @-mentions received
|
||||||
|
when the user is offline.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enable_offline_push_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable mobile notification for private messages and @-mentions received
|
||||||
|
when the user is offline.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enable_online_push_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable mobile notification for private messages and @-mentions received
|
||||||
|
when the user is online.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enable_digest_emails
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable digest emails when the user is away.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enable_login_emails
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Enable email notifications for new logins to account.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: message_content_in_email_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Include the message's content in email notifications for new messages.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: pm_content_in_desktop_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Include content of private messages in desktop notifications.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: wildcard_mentions_notify
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Whether wildcard mentions (E.g. @**all**) should send notifications
|
||||||
|
like a personal mention.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: desktop_icon_count_display
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Unread count summary (appears in desktop sidebar and browser tab)
|
||||||
|
|
||||||
|
* 1 - All unreads
|
||||||
|
* 2 - Private messages and mentions
|
||||||
|
* 3 - None
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
enum:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
example: 1
|
||||||
|
- name: realm_name_in_notifications
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Include organization name in subject of message notification emails.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: presence_enabled
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Display the presence status to other users when online.
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
- name: enter_sends
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Whether pressing Enter in the compose box sends a message
|
||||||
|
(or saves a message edit).
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Success
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: "#/components/schemas/JsonSuccessBase"
|
||||||
|
- $ref: "#/components/schemas/SuccessDescription"
|
||||||
|
- additionalProperties: false
|
||||||
|
properties:
|
||||||
|
result: {}
|
||||||
|
msg: {}
|
||||||
|
ignored_parameters_unsupported:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: |
|
||||||
|
This field lists any parameters sent in the request that are not
|
||||||
|
supported by the endpoint. While this can be expected, e.g. when sending
|
||||||
|
both current and legacy names for a parameter to a Zulip server of
|
||||||
|
unknown version, this often indicates a bug in the client
|
||||||
|
implementation or an attempt to configure a new feature, while
|
||||||
|
connected to an older Zulip server that does not support the feature.
|
||||||
|
example:
|
||||||
|
{
|
||||||
|
"ignored_parameters_unsupported":
|
||||||
|
["desktop_notifications", "demote_streams"],
|
||||||
|
"msg": "",
|
||||||
|
"result": "success",
|
||||||
|
}
|
||||||
|
|
||||||
/users/me/subscriptions/properties:
|
/users/me/subscriptions/properties:
|
||||||
post:
|
post:
|
||||||
operationId: update-subscription-settings
|
operationId: update-subscription-settings
|
||||||
|
|
|
@ -18,6 +18,7 @@ from zerver.lib.actions import (
|
||||||
do_scrub_realm,
|
do_scrub_realm,
|
||||||
do_send_realm_reactivation_email,
|
do_send_realm_reactivation_email,
|
||||||
do_set_realm_property,
|
do_set_realm_property,
|
||||||
|
do_set_realm_user_default_setting,
|
||||||
)
|
)
|
||||||
from zerver.lib.realm_description import get_realm_rendered_description, get_realm_text_description
|
from zerver.lib.realm_description import get_realm_rendered_description, get_realm_text_description
|
||||||
from zerver.lib.send_email import send_future_email
|
from zerver.lib.send_email import send_future_email
|
||||||
|
@ -29,6 +30,7 @@ from zerver.models import (
|
||||||
Message,
|
Message,
|
||||||
Realm,
|
Realm,
|
||||||
RealmAuditLog,
|
RealmAuditLog,
|
||||||
|
RealmUserDefault,
|
||||||
ScheduledEmail,
|
ScheduledEmail,
|
||||||
Stream,
|
Stream,
|
||||||
UserMessage,
|
UserMessage,
|
||||||
|
@ -818,6 +820,97 @@ class RealmAPITest(ZulipTestCase):
|
||||||
with self.subTest(property=prop):
|
with self.subTest(property=prop):
|
||||||
self.do_test_realm_update_api(prop)
|
self.do_test_realm_update_api(prop)
|
||||||
|
|
||||||
|
def update_with_realm_default_api(self, name: str, val: Any) -> None:
|
||||||
|
if not isinstance(val, str):
|
||||||
|
val = orjson.dumps(val).decode()
|
||||||
|
result = self.client_patch("/json/realm/user_settings_defaults", {name: val})
|
||||||
|
self.assert_json_success(result)
|
||||||
|
|
||||||
|
def do_test_realm_default_setting_update_api(self, name: str) -> None:
|
||||||
|
bool_tests: List[bool] = [False, True]
|
||||||
|
test_values: Dict[str, Any] = dict(
|
||||||
|
color_scheme=UserProfile.COLOR_SCHEME_CHOICES,
|
||||||
|
default_view=["recent_topics", "all_messages"],
|
||||||
|
emojiset=[emojiset["key"] for emojiset in RealmUserDefault.emojiset_choices()],
|
||||||
|
demote_inactive_streams=UserProfile.DEMOTE_STREAMS_CHOICES,
|
||||||
|
desktop_icon_count_display=[1, 2, 3],
|
||||||
|
notification_sound=["zulip", "ding"],
|
||||||
|
email_notifications_batching_period_seconds=[120, 300],
|
||||||
|
)
|
||||||
|
|
||||||
|
vals = test_values.get(name)
|
||||||
|
property_type = RealmUserDefault.property_types[name]
|
||||||
|
|
||||||
|
if property_type is bool:
|
||||||
|
vals = bool_tests
|
||||||
|
|
||||||
|
if vals is None:
|
||||||
|
raise AssertionError(f"No test created for {name}")
|
||||||
|
|
||||||
|
realm = get_realm("zulip")
|
||||||
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
||||||
|
do_set_realm_user_default_setting(realm_user_default, name, vals[0], acting_user=None)
|
||||||
|
|
||||||
|
for val in vals[1:]:
|
||||||
|
self.update_with_realm_default_api(name, val)
|
||||||
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
||||||
|
self.assertEqual(getattr(realm_user_default, name), val)
|
||||||
|
|
||||||
|
self.update_with_realm_default_api(name, vals[0])
|
||||||
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
||||||
|
self.assertEqual(getattr(realm_user_default, name), vals[0])
|
||||||
|
|
||||||
|
def test_update_default_realm_settings(self) -> None:
|
||||||
|
for prop in RealmUserDefault.property_types:
|
||||||
|
# enable_marketing_emails setting is not actually used and thus cannot be updated
|
||||||
|
# using this endpoint. It is included in notification_setting_types only for avoiding
|
||||||
|
# duplicate code. default_language and twenty_four_hour_time are currently present
|
||||||
|
# in Realm table also and thus are updated using '/realm' endpoint, but those
|
||||||
|
# will be removed in future and the settings in RealmUserDefault table will be used.
|
||||||
|
if prop in ["default_language", "twenty_four_hour_time", "enable_marketing_emails"]:
|
||||||
|
continue
|
||||||
|
self.do_test_realm_default_setting_update_api(prop)
|
||||||
|
|
||||||
|
def test_invalid_default_notification_sound_value(self) -> None:
|
||||||
|
result = self.client_patch(
|
||||||
|
"/json/realm/user_settings_defaults", {"notification_sound": "invalid"}
|
||||||
|
)
|
||||||
|
self.assert_json_error(result, "Invalid notification sound 'invalid'")
|
||||||
|
|
||||||
|
result = self.client_patch(
|
||||||
|
"/json/realm/user_settings_defaults", {"notification_sound": "zulip"}
|
||||||
|
)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
realm = get_realm("zulip")
|
||||||
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
||||||
|
self.assertEqual(realm_user_default.notification_sound, "zulip")
|
||||||
|
|
||||||
|
def test_invalid_email_notifications_batching_period_setting(self) -> None:
|
||||||
|
result = self.client_patch(
|
||||||
|
"/json/realm/user_settings_defaults",
|
||||||
|
{"email_notifications_batching_period_seconds": -1},
|
||||||
|
)
|
||||||
|
self.assert_json_error(result, "Invalid email batching period: -1 seconds")
|
||||||
|
|
||||||
|
result = self.client_patch(
|
||||||
|
"/json/realm/user_settings_defaults",
|
||||||
|
{"email_notifications_batching_period_seconds": 7 * 24 * 60 * 60 + 10},
|
||||||
|
)
|
||||||
|
self.assert_json_error(result, "Invalid email batching period: 604810 seconds")
|
||||||
|
|
||||||
|
def test_ignored_parameters_in_realm_default_endpoint(self) -> None:
|
||||||
|
params = {"starred_message_counts": orjson.dumps(False).decode(), "emoji_set": "twitter"}
|
||||||
|
json_result = self.client_patch("/json/realm/user_settings_defaults", params)
|
||||||
|
self.assert_json_success(json_result)
|
||||||
|
|
||||||
|
realm = get_realm("zulip")
|
||||||
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
||||||
|
self.assertEqual(realm_user_default.starred_message_counts, False)
|
||||||
|
|
||||||
|
result = orjson.loads(json_result.content)
|
||||||
|
self.assertIn("ignored_parameters_unsupported", result)
|
||||||
|
self.assertEqual(result["ignored_parameters_unsupported"], ["emoji_set"])
|
||||||
|
|
||||||
def test_update_realm_allow_message_editing(self) -> None:
|
def test_update_realm_allow_message_editing(self) -> None:
|
||||||
"""Tests updating the realm property 'allow_message_editing'."""
|
"""Tests updating the realm property 'allow_message_editing'."""
|
||||||
self.set_up_db("allow_message_editing", False)
|
self.set_up_db("allow_message_editing", False)
|
||||||
|
|
|
@ -17,6 +17,7 @@ from zerver.lib.actions import (
|
||||||
do_set_realm_notifications_stream,
|
do_set_realm_notifications_stream,
|
||||||
do_set_realm_property,
|
do_set_realm_property,
|
||||||
do_set_realm_signup_notifications_stream,
|
do_set_realm_signup_notifications_stream,
|
||||||
|
do_set_realm_user_default_setting,
|
||||||
)
|
)
|
||||||
from zerver.lib.exceptions import JsonableError, OrganizationOwnerRequired
|
from zerver.lib.exceptions import JsonableError, OrganizationOwnerRequired
|
||||||
from zerver.lib.i18n import get_available_language_codes
|
from zerver.lib.i18n import get_available_language_codes
|
||||||
|
@ -30,10 +31,12 @@ from zerver.lib.validator import (
|
||||||
check_dict,
|
check_dict,
|
||||||
check_int,
|
check_int,
|
||||||
check_int_in,
|
check_int_in,
|
||||||
|
check_settings_values,
|
||||||
|
check_string_in,
|
||||||
check_string_or_int,
|
check_string_or_int,
|
||||||
to_non_negative_int,
|
to_non_negative_int,
|
||||||
)
|
)
|
||||||
from zerver.models import Realm, UserProfile
|
from zerver.models import Realm, RealmUserDefault, UserProfile
|
||||||
|
|
||||||
|
|
||||||
@require_realm_admin
|
@require_realm_admin
|
||||||
|
@ -275,3 +278,100 @@ def realm_reactivation(request: HttpRequest, confirmation_key: str) -> HttpRespo
|
||||||
do_reactivate_realm(realm)
|
do_reactivate_realm(realm)
|
||||||
context = {"realm": realm}
|
context = {"realm": realm}
|
||||||
return render(request, "zerver/realm_reactivation.html", context)
|
return render(request, "zerver/realm_reactivation.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
emojiset_choices = {emojiset["key"] for emojiset in RealmUserDefault.emojiset_choices()}
|
||||||
|
default_view_options = ["recent_topics", "all_messages"]
|
||||||
|
|
||||||
|
|
||||||
|
@require_realm_admin
|
||||||
|
@has_request_variables
|
||||||
|
def update_realm_user_settings_defaults(
|
||||||
|
request: HttpRequest,
|
||||||
|
user_profile: UserProfile,
|
||||||
|
dense_mode: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
starred_message_counts: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
fluid_layout_width: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
high_contrast_mode: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
color_scheme: Optional[int] = REQ(
|
||||||
|
json_validator=check_int_in(UserProfile.COLOR_SCHEME_CHOICES), default=None
|
||||||
|
),
|
||||||
|
translate_emoticons: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
default_view: Optional[str] = REQ(
|
||||||
|
str_validator=check_string_in(default_view_options), default=None
|
||||||
|
),
|
||||||
|
left_side_userlist: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
emojiset: Optional[str] = REQ(str_validator=check_string_in(emojiset_choices), default=None),
|
||||||
|
demote_inactive_streams: Optional[int] = REQ(
|
||||||
|
json_validator=check_int_in(UserProfile.DEMOTE_STREAMS_CHOICES), default=None
|
||||||
|
),
|
||||||
|
enable_stream_desktop_notifications: Optional[bool] = REQ(
|
||||||
|
json_validator=check_bool, default=None
|
||||||
|
),
|
||||||
|
enable_stream_email_notifications: Optional[bool] = REQ(
|
||||||
|
json_validator=check_bool, default=None
|
||||||
|
),
|
||||||
|
enable_stream_push_notifications: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
enable_stream_audible_notifications: Optional[bool] = REQ(
|
||||||
|
json_validator=check_bool, default=None
|
||||||
|
),
|
||||||
|
wildcard_mentions_notify: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
notification_sound: Optional[str] = REQ(default=None),
|
||||||
|
enable_desktop_notifications: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
enable_sounds: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
enable_offline_email_notifications: Optional[bool] = REQ(
|
||||||
|
json_validator=check_bool, default=None
|
||||||
|
),
|
||||||
|
enable_offline_push_notifications: Optional[bool] = REQ(
|
||||||
|
json_validator=check_bool, default=None
|
||||||
|
),
|
||||||
|
enable_online_push_notifications: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
enable_digest_emails: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
enable_login_emails: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
# enable_marketing_emails is not included here, since we don't at
|
||||||
|
# present allow organizations to customize this. (The user's selection
|
||||||
|
# in the signup form takes precedence over RealmUserDefault).
|
||||||
|
#
|
||||||
|
# We may want to change this model in the future, since some SSO signups
|
||||||
|
# do not offer an opportunity to prompt the user at all during signup.
|
||||||
|
message_content_in_email_notifications: Optional[bool] = REQ(
|
||||||
|
json_validator=check_bool, default=None
|
||||||
|
),
|
||||||
|
pm_content_in_desktop_notifications: Optional[bool] = REQ(
|
||||||
|
json_validator=check_bool, default=None
|
||||||
|
),
|
||||||
|
desktop_icon_count_display: Optional[int] = REQ(
|
||||||
|
json_validator=check_int_in(UserProfile.DESKTOP_ICON_COUNT_DISPLAY_CHOICES), default=None
|
||||||
|
),
|
||||||
|
realm_name_in_notifications: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
presence_enabled: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
enter_sends: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
enable_drafts_synchronization: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
|
email_notifications_batching_period_seconds: Optional[int] = REQ(
|
||||||
|
json_validator=check_int, default=None
|
||||||
|
),
|
||||||
|
) -> HttpResponse:
|
||||||
|
if notification_sound is not None or email_notifications_batching_period_seconds is not None:
|
||||||
|
check_settings_values(notification_sound, email_notifications_batching_period_seconds)
|
||||||
|
|
||||||
|
realm_user_default = RealmUserDefault.objects.get(realm=user_profile.realm)
|
||||||
|
request_settings = {
|
||||||
|
k: v for k, v in list(locals().items()) if (k in RealmUserDefault.property_types)
|
||||||
|
}
|
||||||
|
for k, v in list(request_settings.items()):
|
||||||
|
if v is not None and getattr(realm_user_default, k) != v:
|
||||||
|
do_set_realm_user_default_setting(realm_user_default, k, v, acting_user=user_profile)
|
||||||
|
|
||||||
|
# TODO: Extract `ignored_parameters_unsupported` to be a common feature of the REQ framework.
|
||||||
|
from zerver.lib.request import RequestNotes
|
||||||
|
|
||||||
|
request_notes = RequestNotes.get_notes(request)
|
||||||
|
for req_var in request.POST:
|
||||||
|
if req_var not in request_notes.processed_parameters:
|
||||||
|
request_notes.ignored_parameters.add(req_var)
|
||||||
|
|
||||||
|
result: Dict[str, Any] = {}
|
||||||
|
if len(request_notes.ignored_parameters) > 0:
|
||||||
|
result["ignored_parameters_unsupported"] = list(request_notes.ignored_parameters)
|
||||||
|
|
||||||
|
return json_success(result)
|
||||||
|
|
|
@ -105,6 +105,7 @@ from zerver.views.realm import (
|
||||||
deactivate_realm,
|
deactivate_realm,
|
||||||
realm_reactivation,
|
realm_reactivation,
|
||||||
update_realm,
|
update_realm,
|
||||||
|
update_realm_user_settings_defaults,
|
||||||
)
|
)
|
||||||
from zerver.views.realm_domains import (
|
from zerver.views.realm_domains import (
|
||||||
create_realm_domain,
|
create_realm_domain,
|
||||||
|
@ -245,6 +246,7 @@ if settings.TWO_FACTOR_AUTHENTICATION_ENABLED:
|
||||||
v1_api_and_json_patterns = [
|
v1_api_and_json_patterns = [
|
||||||
# realm-level calls
|
# realm-level calls
|
||||||
rest_path("realm", PATCH=update_realm),
|
rest_path("realm", PATCH=update_realm),
|
||||||
|
rest_path("realm/user_settings_defaults", PATCH=update_realm_user_settings_defaults),
|
||||||
path("realm/subdomain/<subdomain>", check_subdomain_available),
|
path("realm/subdomain/<subdomain>", check_subdomain_available),
|
||||||
# realm/domains -> zerver.views.realm_domains
|
# realm/domains -> zerver.views.realm_domains
|
||||||
rest_path("realm/domains", GET=list_realm_domains, POST=create_realm_domain),
|
rest_path("realm/domains", GET=list_realm_domains, POST=create_realm_domain),
|
||||||
|
|
Loading…
Reference in New Issue