diff --git a/static/js/admin.js b/static/js/admin.js index bafb4dcbcc..519b684d84 100644 --- a/static/js/admin.js +++ b/static/js/admin.js @@ -381,6 +381,10 @@ function _setup_page() { realm_restricted_to_domain: page_params.realm_restricted_to_domain, realm_invite_required: page_params.realm_invite_required, realm_invite_by_admins_only: page_params.realm_invite_by_admins_only, + realm_inline_image_preview: page_params.realm_inline_image_preview, + server_inline_image_preview: page_params.server_inline_image_preview, + realm_inline_url_embed_preview: page_params.realm_inline_url_embed_preview, + server_inline_url_embed_preview: page_params.server_inline_url_embed_preview, realm_authentication_methods: page_params.realm_authentication_methods, realm_create_stream_by_admins_only: page_params.realm_create_stream_by_admins_only, realm_name_changes_disabled: page_params.realm_name_changes_disabled, @@ -623,6 +627,8 @@ function _setup_page() { var restricted_to_domain_status = $("#admin-realm-restricted-to-domain-status").expectOne(); var invite_required_status = $("#admin-realm-invite-required-status").expectOne(); var invite_by_admins_only_status = $("#admin-realm-invite-by-admins-only-status").expectOne(); + var inline_image_preview_status = $("#admin-realm-inline-image-preview-status").expectOne(); + var inline_url_embed_preview_status = $("#admin-realm-inline-url-embed-preview-status").expectOne(); var authentication_methods_status = $("#admin-realm-authentication-methods-status").expectOne(); var create_stream_by_admins_only_status = $("#admin-realm-create-stream-by-admins-only-status").expectOne(); var name_changes_disabled_status = $("#admin-realm-name-changes-disabled-status").expectOne(); @@ -636,6 +642,8 @@ function _setup_page() { restricted_to_domain_status.hide(); invite_required_status.hide(); invite_by_admins_only_status.hide(); + inline_image_preview_status.hide(); + inline_url_embed_preview_status.hide(); authentication_methods_status.hide(); create_stream_by_admins_only_status.hide(); name_changes_disabled_status.hide(); @@ -653,6 +661,8 @@ function _setup_page() { var new_restricted = $("#id_realm_restricted_to_domain").prop("checked"); var new_invite = $("#id_realm_invite_required").prop("checked"); var new_invite_by_admins_only = $("#id_realm_invite_by_admins_only").prop("checked"); + var new_inline_image_preview = $("#id_realm_inline_image_preview").prop("checked"); + var new_inline_url_embed_preview = $("#id_realm_inline_url_embed_preview").prop("checked"); var new_create_stream_by_admins_only = $("#id_realm_create_stream_by_admins_only").prop("checked"); var new_name_changes_disabled = $("#id_realm_name_changes_disabled").prop("checked"); var new_email_changes_disabled = $("#id_realm_email_changes_disabled").prop("checked"); @@ -685,6 +695,8 @@ function _setup_page() { restricted_to_domain: JSON.stringify(new_restricted), invite_required: JSON.stringify(new_invite), invite_by_admins_only: JSON.stringify(new_invite_by_admins_only), + inline_image_preview: JSON.stringify(new_inline_image_preview), + inline_url_embed_preview: JSON.stringify(new_inline_url_embed_preview), authentication_methods: JSON.stringify(new_auth_methods), create_stream_by_admins_only: JSON.stringify(new_create_stream_by_admins_only), name_changes_disabled: JSON.stringify(new_name_changes_disabled), @@ -728,6 +740,20 @@ function _setup_page() { ui_report.success(i18n.t("Any user may now invite new users!"), invite_by_admins_only_status); } } + if (response_data.inline_image_preview !== undefined) { + if (response_data.inline_image_preview) { + ui.report_success(i18n.t("Previews of uploaded and linked images will be shown!"), inline_image_preview_status); + } else { + ui.report_success(i18n.t("Previews of uploaded and linked images will not be shown!"), inline_image_preview_status); + } + } + if (response_data.inline_url_embed_preview !== undefined) { + if (response_data.inline_url_embed_preview) { + ui.report_success(i18n.t("Previews for linked websites will be shown!"), inline_url_embed_preview_status); + } else { + ui.report_success(i18n.t("Previews for linked websites will not be shown!"), inline_url_embed_preview_status); + } + } if (response_data.create_stream_by_admins_only !== undefined) { if (response_data.create_stream_by_admins_only) { ui_report.success(i18n.t("Only administrators may now create new streams!"), create_stream_by_admins_only_status); diff --git a/static/js/server_events.js b/static/js/server_events.js index ca4043ae0e..47dfd0379f 100644 --- a/static/js/server_events.js +++ b/static/js/server_events.js @@ -62,6 +62,10 @@ function dispatch_normal_event(event) { page_params.realm_invite_required = event.value; } else if (event.op === 'update' && event.property === 'invite_by_admins_only') { page_params.realm_invite_by_admins_only = event.value; + } else if (event.op === 'update' && event.property === 'inline_image_preview') { + page_params.realm_inline_image_preview = event.value; + } else if (event.op === 'update' && event.property === 'inline_url_embed_preview') { + page_params.realm_inline_url_embed_preview = event.value; } else if (event.op === 'update' && event.property === 'create_stream_by_admins_only') { page_params.realm_create_stream_by_admins_only = event.value; if (!page_params.is_admin) { diff --git a/static/templates/settings/organization-settings-admin.handlebars b/static/templates/settings/organization-settings-admin.handlebars index bd3b1ed3db..47bcd4e4b7 100644 --- a/static/templates/settings/organization-settings-admin.handlebars +++ b/static/templates/settings/organization-settings-admin.handlebars @@ -7,6 +7,8 @@
+ + @@ -55,6 +57,30 @@ {{t "Only admins may invite" }} + {{#if server_inline_image_preview}} +Check out the debate: http://www.youtube.com/watch?v=hx1mjT73xYE
\n ') + @override_settings(INLINE_IMAGE_PREVIEW=True) + def test_inline_image_preview(self): + # type: () -> None + with_preview = 'http://cdn.wallpapersafari.com/13/6/16eVjx.jpeg
\n ' + without_preview = '' + content = 'http://cdn.wallpapersafari.com/13/6/16eVjx.jpeg' + + sender_user_profile = get_user_profile_by_email("othello@zulip.com") + msg = Message(sender=sender_user_profile, sending_client=get_client("test")) + converted = render_markdown(msg, content) + self.assertEqual(converted, with_preview) + + realm = msg.get_realm() + setattr(realm, 'inline_image_preview', False) + realm.save() + + sender_user_profile = get_user_profile_by_email("othello@zulip.com") + msg = Message(sender=sender_user_profile, sending_client=get_client("test")) + converted = render_markdown(msg, content) + self.assertEqual(converted, without_preview) + + @override_settings(INLINE_IMAGE_PREVIEW=False) + def test_image_preview_enabled_for_realm(self): + # type: () -> None + ret = bugdown.image_preview_enabled_for_realm() + self.assertEqual(ret, False) + + settings.INLINE_IMAGE_PREVIEW = True + + sender_user_profile = get_user_profile_by_email("othello@zulip.com") + bugdown.current_message = copy.deepcopy(Message(sender=sender_user_profile, sending_client=get_client("test"))) + realm = bugdown.current_message.get_realm() + + ret = bugdown.image_preview_enabled_for_realm() + self.assertEqual(ret, realm.inline_image_preview) + + bugdown.current_message = None + ret = bugdown.image_preview_enabled_for_realm() + self.assertEqual(ret, True) + + @override_settings(INLINE_URL_EMBED_PREVIEW=False) + def test_url_embed_preview_enabled_for_realm(self): + # type: () -> None + sender_user_profile = get_user_profile_by_email("othello@zulip.com") + message = copy.deepcopy(Message(sender=sender_user_profile, sending_client=get_client("test"))) + realm = message.get_realm() + + ret = bugdown.url_embed_preview_enabled_for_realm(message) + self.assertEqual(ret, False) + + settings.INLINE_URL_EMBED_PREVIEW = True + + ret = bugdown.url_embed_preview_enabled_for_realm(message) + self.assertEqual(ret, realm.inline_image_preview) + + message = None + ret = bugdown.url_embed_preview_enabled_for_realm(message) + self.assertEqual(ret, True) + def test_inline_dropbox(self): # type: () -> None msg = 'Look at how hilarious our old office was: https://www.dropbox.com/s/ymdijjcg67hv2ta/IMG_0923.JPG' diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index 18cd3a5ac1..46fa74c072 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -51,6 +51,8 @@ from zerver.lib.actions import ( do_set_realm_invite_by_admins_only, do_set_name_changes_disabled, do_set_email_changes_disabled, + do_set_realm_inline_image_preview, + do_set_realm_inline_url_embed_preview, do_set_realm_message_editing, do_set_realm_default_language, do_set_realm_authentication_methods, @@ -711,6 +713,34 @@ class EventsRegisterTest(ZulipTestCase): error = schema_checker('events[0]', events[0]) self.assert_on_error(error) + def test_change_realm_inline_image_preview(self): + # type: () -> None + schema_checker = check_dict([ + ('type', equals('realm')), + ('op', equals('update')), + ('property', equals('inline_image_preview')), + ('value', check_bool), + ]) + do_set_realm_inline_image_preview(self.user_profile.realm, inline_image_preview=False) + for inline_image_preview in (True, False): + events = self.do_test(lambda: do_set_realm_inline_image_preview(self.user_profile.realm, inline_image_preview)) + error = schema_checker('events[0]', events[0]) + self.assert_on_error(error) + + def test_change_realm_inline_url_embed_preview(self): + # type: () -> None + schema_checker = check_dict([ + ('type', equals('realm')), + ('op', equals('update')), + ('property', equals('inline_url_embed_preview')), + ('value', check_bool), + ]) + do_set_realm_inline_url_embed_preview(self.user_profile.realm, inline_url_embed_preview=False) + for inline_url_embed_preview in (True, False): + events = self.do_test(lambda: do_set_realm_inline_url_embed_preview(self.user_profile.realm, inline_url_embed_preview)) + error = schema_checker('events[0]', events[0]) + self.assert_on_error(error) + def test_change_realm_default_language(self): # type: () -> None schema_checker = check_dict([ diff --git a/zerver/tests/test_home.py b/zerver/tests/test_home.py index 0f92fa9701..62d6327dbb 100644 --- a/zerver/tests/test_home.py +++ b/zerver/tests/test_home.py @@ -105,6 +105,8 @@ class HomeTest(ZulipTestCase): "realm_filters", "realm_icon_source", "realm_icon_url", + "realm_inline_image_preview", + "realm_inline_url_embed_preview", "realm_invite_by_admins_only", "realm_invite_required", "realm_message_content_edit_limit_seconds", @@ -117,6 +119,8 @@ class HomeTest(ZulipTestCase): "referrals", "save_stacktraces", "server_generation", + "server_inline_image_preview", + "server_inline_url_embed_preview", "server_uri", "share_the_love", "show_digest_email", diff --git a/zerver/tests/test_link_embed.py b/zerver/tests/test_link_embed.py index 43e9906d9b..0054f16e9e 100644 --- a/zerver/tests/test_link_embed.py +++ b/zerver/tests/test_link_embed.py @@ -256,6 +256,20 @@ class PreviewTestCase(ZulipTestCase): msg = self._send_message_with_test_org_url(sender_email='prospero@zulip.com') self.assertIn(embedded_link, msg.rendered_content) + def test_inline_url_embed_preview(self): + # type: () -> None + with_preview = '\n ' + without_preview = '' + msg = self._send_message_with_test_org_url(sender_email='hamlet@zulip.com') + self.assertEqual(msg.rendered_content, with_preview) + + realm = msg.get_realm() + setattr(realm, 'inline_url_embed_preview', False) + realm.save() + + msg = self._send_message_with_test_org_url(sender_email='prospero@zulip.com', queue_should_run=False) + self.assertEqual(msg.rendered_content, without_preview) + def test_http_error_get_data(self): # type: () -> None url = 'http://test.org/' diff --git a/zerver/tests/test_realm.py b/zerver/tests/test_realm.py index e9f6ad74dc..ac6b2fbf5e 100644 --- a/zerver/tests/test_realm.py +++ b/zerver/tests/test_realm.py @@ -135,6 +135,20 @@ class RealmTest(ZulipTestCase): realm = update_with_api(invite_by_admins_only=False) self.assertEqual(realm.invite_by_admins_only, False) + # inline_image_preview + set_up_db('inline_image_preview', True) + realm = update_with_api(inline_image_preview=False) + self.assertEqual(realm.inline_image_preview, False) + realm = update_with_api(inline_image_preview=True) + self.assertEqual(realm.inline_image_preview, True) + + # inline_url_embed_preview + set_up_db('inline_url_embed_preview', False) + realm = update_with_api(inline_url_embed_preview=True) + self.assertEqual(realm.inline_url_embed_preview, True) + realm = update_with_api(inline_url_embed_preview=False) + self.assertEqual(realm.inline_url_embed_preview, False) + # create_stream_by_admins_only set_up_db('create_stream_by_admins_only', False) realm = update_with_api(create_stream_by_admins_only=True) diff --git a/zerver/views/home.py b/zerver/views/home.py index d7ef494f63..d62037ef78 100644 --- a/zerver/views/home.py +++ b/zerver/views/home.py @@ -206,6 +206,8 @@ def home_real(request): server_generation = settings.SERVER_GENERATION, use_websockets = settings.USE_WEBSOCKETS, save_stacktraces = settings.SAVE_FRONTEND_STACKTRACES, + server_inline_image_preview = settings.INLINE_IMAGE_PREVIEW, + server_inline_url_embed_preview = settings.INLINE_URL_EMBED_PREVIEW, # realm data. # TODO: Move all of these data to register_ret and pull from there @@ -299,6 +301,8 @@ def home_real(request): 'realm_icon_source', 'realm_icon_url', 'realm_invite_by_admins_only', + 'realm_inline_image_preview', + 'realm_inline_url_embed_preview', 'realm_invite_required', 'realm_message_content_edit_limit_seconds', 'realm_name', diff --git a/zerver/views/messages.py b/zerver/views/messages.py index 9dc6c70e6e..70c69d5fd0 100644 --- a/zerver/views/messages.py +++ b/zerver/views/messages.py @@ -972,6 +972,7 @@ def update_message_backend(request, user_profile, message, ignored_user_message = access_message(user_profile, message_id) # You only have permission to edit a message if: + # you change this value also change those two parameters in message_edit.js. # 1. You sent it, OR: # 2. This is a topic-only edit for a (no topic) message, OR: # 3. This is a topic-only edit and you are an admin. @@ -1034,7 +1035,7 @@ def update_message_backend(request, user_profile, propagate_mode, content, rendered_content) # Include the number of messages changed in the logs request._log_data['extra'] = "[%s]" % (number_changed,) - if links_for_embed and getattr(settings, 'INLINE_URL_EMBED_PREVIEW', None): + if links_for_embed and bugdown.url_embed_preview_enabled_for_realm(message): event_data = { 'message_id': message.id, 'message_content': message.content, diff --git a/zerver/views/realm.py b/zerver/views/realm.py index c7b09add5d..b9d39c83b8 100644 --- a/zerver/views/realm.py +++ b/zerver/views/realm.py @@ -12,6 +12,8 @@ from zerver.lib.actions import ( do_set_realm_invite_by_admins_only, do_set_name_changes_disabled, do_set_email_changes_disabled, + do_set_realm_inline_image_preview, + do_set_realm_inline_url_embed_preview, do_set_realm_add_emoji_by_admins_only, do_set_realm_invite_required, do_set_realm_message_editing, @@ -35,6 +37,8 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default invite_by_admins_only=REQ(validator=check_bool, default=None), name_changes_disabled=REQ(validator=check_bool, default=None), email_changes_disabled=REQ(validator=check_bool, default=None), + inline_image_preview=REQ(validator=check_bool, default=None), + inline_url_embed_preview=REQ(validator=check_bool, default=None), create_stream_by_admins_only=REQ(validator=check_bool, default=None), add_emoji_by_admins_only=REQ(validator=check_bool, default=None), allow_message_editing=REQ(validator=check_bool, default=None), @@ -42,7 +46,7 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default default_language=REQ(validator=check_string, default=None), waiting_period_threshold=REQ(converter=to_non_negative_int, default=None), authentication_methods=REQ(validator=check_dict([]), default=None)): - # type: (HttpRequest, UserProfile, Optional[str], Optional[str], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[int], Optional[str], Optional[int], Optional[dict]) -> HttpResponse + # type: (HttpRequest, UserProfile, Optional[str], Optional[str], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[int], Optional[str], Optional[int], Optional[dict]) -> HttpResponse # Validation for default_language if default_language is not None and default_language not in get_available_language_codes(): raise JsonableError(_("Invalid language '%s'" % (default_language,))) @@ -71,6 +75,12 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default if email_changes_disabled is not None and realm.email_changes_disabled != email_changes_disabled: do_set_email_changes_disabled(realm, email_changes_disabled) data['email_changes_disabled'] = email_changes_disabled + if inline_image_preview is not None and realm.inline_image_preview != inline_image_preview: + do_set_realm_inline_image_preview(realm, inline_image_preview) + data['inline_image_preview'] = inline_image_preview + if inline_url_embed_preview is not None and realm.inline_url_embed_preview != inline_url_embed_preview: + do_set_realm_inline_url_embed_preview(realm, inline_url_embed_preview) + data['inline_url_embed_preview'] = inline_url_embed_preview if authentication_methods is not None and realm.authentication_methods_dict() != authentication_methods: if True not in list(authentication_methods.values()): return json_error(_("At least one authentication method must be enabled."),