From 4c2995c613508e2ed9cdb84e03be2a58003a6789 Mon Sep 17 00:00:00 2001 From: evykassirer Date: Wed, 9 Aug 2023 13:30:51 -0700 Subject: [PATCH] stream settings: Warn users before locking them out of a stream. Organization owners can make streams private even if they're not subscribed to them, but cannot access private streams they're not subscribed to. This means they're able to lock themself out of streams. This change warns users of this and give them a chance to subscribe. Fixes #26437. --- web/src/settings_org.js | 48 +++++++++++++++++++ web/src/stream_edit.js | 30 ++++++++++++ .../stream_settings/stream_settings.hbs | 2 + 3 files changed, 80 insertions(+) diff --git a/web/src/settings_org.js b/web/src/settings_org.js index 0db8644801..335dbec94c 100644 --- a/web/src/settings_org.js +++ b/web/src/settings_org.js @@ -1,11 +1,13 @@ import $ from "jquery"; import pygments_data from "../generated/pygments_data.json"; +import render_compose_banner from "../templates/compose_banner/compose_banner.hbs"; import render_settings_deactivate_realm_modal from "../templates/confirm_dialog/confirm_deactivate_realm.hbs"; import render_settings_admin_auth_methods_list from "../templates/settings/admin_auth_methods_list.hbs"; import * as blueslip from "./blueslip"; import * as channel from "./channel"; +import * as compose_banner from "./compose_banner"; import {csrf_token} from "./csrf"; import * as dialog_widget from "./dialog_widget"; import * as dropdown_widget from "./dropdown_widget"; @@ -994,6 +996,19 @@ export function check_property_changed(elem, for_realm_default_settings, sub) { return current_val !== proposed_val; } +function switching_to_private(properties_elements, for_realm_default_settings) { + for (const elem of properties_elements) { + const $elem = $(elem); + const property_name = extract_property_name($elem, for_realm_default_settings); + if (property_name !== "stream_privacy") { + continue; + } + const proposed_val = get_input_element_value($elem, "radio-group"); + return proposed_val === "invite-only-public-history" || proposed_val === "invite-only"; + } + return false; +} + export function save_discard_widget_status_handler($subsection, for_realm_default_settings, sub) { $subsection.find(".subsection-failed-status p").hide(); $subsection.find(".save-button").show(); @@ -1005,6 +1020,39 @@ export function save_discard_widget_status_handler($subsection, for_realm_defaul const $save_btn_controls = $subsection.find(".subsection-header .save-button-controls"); const button_state = show_change_process_button ? "unsaved" : "discarded"; change_save_button_state($save_btn_controls, button_state); + + // If this widget is for a stream, and the stream isn't currently private + // but being changed to private, and the user changing this setting isn't + // subscribed, we show a warning that they won't be able to access the + // stream after making it private unless they subscribe. + if (!sub) { + return; + } + if ( + button_state === "unsaved" && + !sub.invite_only && + !sub.subscribed && + switching_to_private(properties_elements, for_realm_default_settings) + ) { + if ($("#stream_permission_settings .stream_privacy_warning").length > 0) { + return; + } + const context = { + banner_type: compose_banner.WARNING, + banner_text: $t({ + defaultMessage: + "Only subscribers can access or join private streams, so you will lose access to this stream if you convert it to a private stream while not subscribed to it.", + }), + button_text: $t({defaultMessage: "Subscribe"}), + classname: "stream_privacy_warning", + stream_id: sub.stream_id, + }; + $("#stream_permission_settings .stream-permissions-warning-banner").append( + render_compose_banner(context), + ); + } else { + $("#stream_permission_settings .stream-permissions-warning-banner").empty(); + } } export function init_dropdown_widgets() { diff --git a/web/src/stream_edit.js b/web/src/stream_edit.js index 618edb9057..fca13c3328 100644 --- a/web/src/stream_edit.js +++ b/web/src/stream_edit.js @@ -466,6 +466,36 @@ export function initialize() { return true; }); + $("#streams_overlay_container").on( + "click", + ".stream-permissions-warning-banner .main-view-banner-close-button", + (event) => { + event.preventDefault(); + $("#stream_permission_settings .stream-permissions-warning-banner").empty(); + }, + ); + + $("#streams_overlay_container").on( + "click", + ".stream-permissions-warning-banner .main-view-banner-action-button", + (event) => { + event.preventDefault(); + event.stopPropagation(); + + const $target = $(event.target).parents(".main-view-banner"); + const stream_id = Number.parseInt($target.attr("data-stream-id"), 10); + // Makes sure we take the correct stream_row. + const $stream_row = $( + `#streams_overlay_container div.stream-row[data-stream-id='${CSS.escape( + stream_id, + )}']`, + ); + const sub = sub_store.get(stream_id); + stream_settings_ui.sub_or_unsub(sub, $stream_row); + $("#stream_permission_settings .stream-permissions-warning-banner").empty(); + }, + ); + function save_stream_info(e) { const sub = get_sub_for_target(e.currentTarget); diff --git a/web/templates/stream_settings/stream_settings.hbs b/web/templates/stream_settings/stream_settings.hbs index cdab10c1a3..7867b5c582 100644 --- a/web/templates/stream_settings/stream_settings.hbs +++ b/web/templates/stream_settings/stream_settings.hbs @@ -52,6 +52,8 @@ {{> ../settings/settings_save_discard_widget section_name="stream-permissions" }} +
+ {{> stream_types stream_post_policy_values=../stream_post_policy_values stream_privacy_policy_values=../stream_privacy_policy_values