Skip to content

Commit

Permalink
Merge d4d1574 into 898acc4
Browse files Browse the repository at this point in the history
  • Loading branch information
YJDave committed Dec 21, 2017
2 parents 898acc4 + d4d1574 commit 1fe7ad1
Show file tree
Hide file tree
Showing 17 changed files with 202 additions and 17 deletions.
16 changes: 16 additions & 0 deletions frontend_tests/node_tests/settings_org.js
Expand Up @@ -348,6 +348,20 @@ function test_change_message_editing(change_message_editing) {
assert.equal($('#id_realm_message_content_edit_limit_minutes').prop('disabled'), false);
}

function test_change_message_deleting(change_message_deleting) {
var parent_elem = $.create('deleting-parent-stub');

$('#id_realm_message_content_delete_limit_minutes_label').set_parent(parent_elem);

change_message_deleting.apply({checked: false});
assert(parent_elem.hasClass('control-label-disabled'));
assert.equal($('#id_realm_message_content_delete_limit_minutes').attr('disabled'), true);

change_message_deleting.apply({checked: true});
assert(!parent_elem.hasClass('control-label-disabled'));
assert.equal($('#id_realm_message_content_delete_limit_minutes').prop('disabled'), false);
}

function test_change_invite_required(change_invite_required) {
var parent_elem = $.create('invite-parent-stub');

Expand Down Expand Up @@ -483,6 +497,7 @@ function test_change_allow_subdomains(change_allow_subdomains) {

$('#id_realm_invite_required').change = set_callback('change_invite_required');
$('#id_realm_allow_message_editing').change = set_callback('change_message_editing');
$('#id_realm_allow_message_deleting').change = set_callback('change_message_deleting');
$('#submit-add-realm-domain').click = set_callback('add_realm_domain');
$('.notifications-stream-disable').click = set_callback('disable_notifications_stream');
$('.signup-notifications-stream-disable').click = set_callback('disable_signup_notifications_stream');
Expand Down Expand Up @@ -530,6 +545,7 @@ function test_change_allow_subdomains(change_allow_subdomains) {
test_upload_realm_icon(upload_realm_icon);
test_change_invite_required(callbacks.change_invite_required);
test_change_message_editing(callbacks.change_message_editing);
test_change_message_deleting(callbacks.change_message_deleting);
test_disable_notifications_stream(callbacks.disable_notifications_stream);
test_disable_signup_notifications_stream(callbacks.disable_signup_notifications_stream);
test_change_allow_subdomains(change_allow_subdomains);
Expand Down
2 changes: 2 additions & 0 deletions static/js/admin.js
Expand Up @@ -45,6 +45,8 @@ function _setup_page() {
realm_allow_message_editing: page_params.realm_allow_message_editing,
realm_message_content_edit_limit_minutes:
Math.ceil(page_params.realm_message_content_edit_limit_seconds / 60),
realm_message_content_delete_limit_minutes:
Math.ceil(page_params.realm_message_content_delete_limit_seconds / 60),
realm_message_retention_days: page_params.realm_message_retention_days,
realm_allow_edit_history: page_params.realm_allow_edit_history,
language_list: page_params.language_list,
Expand Down
14 changes: 14 additions & 0 deletions static/js/message_edit.js
Expand Up @@ -57,6 +57,20 @@ function get_editability(message, edit_limit_seconds_buffer) {
}
exports.get_editability = get_editability;

exports.get_deletability = function (message) {

if (page_params.realm_allow_message_deleting && !message.locally_echoed) {
var now = new XDate();
if (page_params.realm_message_content_delete_limit_seconds +
now.diffSeconds(message.timestamp * 1000) > 0 ||
page_params.realm_message_content_delete_limit_seconds === 0) {
return true;
}
}

return false;
};

// Returns true if the edit task should end.
exports.save = function (row, from_topic_edited_only) {
var msg_list = current_msg_list;
Expand Down
4 changes: 3 additions & 1 deletion static/js/popovers.js
Expand Up @@ -169,11 +169,13 @@ exports.toggle_actions_popover = function (element, id) {
message.subject &&
muting.is_topic_muted(message.stream, message.subject);

var can_delete_message = message_edit.get_deletability(message);

var should_display_edit_history_option = _.any(message.edit_history, function (entry) {
return entry.prev_content !== undefined;
}) && page_params.realm_allow_edit_history;
var should_display_delete_option = page_params.is_admin ||
(message.sent_by_me && page_params.realm_allow_message_deleting);
(message.sent_by_me && page_params.realm_allow_message_deleting && can_delete_message);
var args = {
message: message,
use_edit_icon: use_edit_icon,
Expand Down
50 changes: 45 additions & 5 deletions static/js/settings_org.js
Expand Up @@ -249,11 +249,6 @@ function _set_up() {
type: 'text',
msg: i18n.t("Default language changed!"),
},
allow_message_deleting: {
type: 'bool',
checked_msg: i18n.t("Users can delete their messages!"),
unchecked_msg: i18n.t("Users can no longer delete their messages!"),
},
allow_edit_history: {
type: 'bool',
checked_msg: i18n.t("Users can view message edit history!"),
Expand Down Expand Up @@ -390,6 +385,16 @@ function _set_up() {
}
});

$("#id_realm_allow_message_deleting").change(function () {
if (this.checked) {
$("#id_realm_message_content_delete_limit_minutes").prop("disabled", false);
$("#id_realm_message_content_delete_limit_minutes_label").parent().removeClass("control-label-disabled");
} else {
$("#id_realm_message_content_delete_limit_minutes").attr("disabled", true);
$("#id_realm_message_content_delete_limit_minutes_label").parent().addClass("control-label-disabled");
}
});

$(".organization").on("submit", "form.org-settings-form", function (e) {
e.preventDefault();
e.stopPropagation();
Expand All @@ -399,18 +404,23 @@ function _set_up() {
});

var message_editing_status = $("#admin-realm-message-editing-status").expectOne();
var message_deleting_status = $("#admin-realm-allow-message-deleting-status").expectOne();
// grab the first alert available and use it for the status.
var $alerts = $(".settings-section.show .alert").hide();
// grab the first alert available and use it for the status.
var status = $("#admin-realm-notifications-stream-status");

var compose_textarea_edit_limit_minutes = $("#id_realm_message_content_edit_limit_minutes").val();
var new_allow_message_editing = $("#id_realm_allow_message_editing").prop("checked");
var compose_textarea_delete_limit_minutes = $("#id_realm_message_content_delete_limit_minutes").val();
var new_allow_message_deleting = $("#id_realm_allow_message_deleting").prop("checked");

// If allow_message_editing is unchecked, message_content_edit_limit_minutes
// is irrelevant. Hence if allow_message_editing is unchecked, and
// message_content_edit_limit_minutes is poorly formed, we set the latter to
// a default value to prevent the server from returning an error.
// Same logic will be applied to allow_message_deleting and
// message_content_delete_limit_minutes settings.
if (!new_allow_message_editing) {
if ((parseInt(compose_textarea_edit_limit_minutes, 10).toString() !==
compose_textarea_edit_limit_minutes) ||
Expand All @@ -420,12 +430,24 @@ function _set_up() {
}
}

if (!new_allow_message_deleting) {
if ((parseInt(compose_textarea_delete_limit_minutes, 10).toString() !==
compose_textarea_delete_limit_minutes) ||
compose_textarea_delete_limit_minutes < 0) {
// Realm.DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS / 60
compose_textarea_delete_limit_minutes = 2;
}
}

var url = "/json/realm";
var data = {};
data = populate_data_for_request({
allow_message_editing: JSON.stringify(new_allow_message_editing),
message_content_edit_limit_seconds:
JSON.stringify(parseInt(compose_textarea_edit_limit_minutes, 10) * 60),
allow_message_deleting: JSON.stringify(new_allow_message_deleting),
message_content_delete_limit_seconds:
JSON.stringify(parseInt(compose_textarea_delete_limit_minutes, 10) * 60),
}, 'settings');

channel.patch({
Expand Down Expand Up @@ -456,6 +478,24 @@ function _set_up() {
$("#id_realm_message_content_edit_limit_minutes").val(data_message_content_edit_limit_minutes);
}

if (response_data.allow_message_deleting !== undefined) {
var data_message_content_delete_limit_minutes =
Math.ceil(response_data.message_content_delete_limit_seconds / 60);
if (response_data.allow_message_deleting) {
if (response_data.message_content_delete_limit_seconds > 0) {
ui_report.success(
i18n.t("Users can now delete the content of messages which are less than __num_minutes__ minutes old.",
{num_minutes : data_message_content_delete_limit_minutes}),
message_deleting_status);
} else {
ui_report.success(i18n.t("Users can now delete the content of all their past messages!"), message_deleting_status);
}
} else {
ui_report.success(i18n.t("Users can no longer delete their past messages!"), message_deleting_status);
}
$("#id_realm_message_content_delete_limit_minutes").val(data_message_content_delete_limit_minutes);
}

process_response_data(response_data, 'settings');
// Check if no changes made
var no_changes_made = true;
Expand Down
5 changes: 5 additions & 0 deletions static/styles/settings.css
Expand Up @@ -447,6 +447,11 @@ input[type=checkbox].inline-block {
text-align: right;
}

.admin-realm-message-content-delete-limit-minutes {
width: 5ch;
text-align: right;
}

.admin-realm-message-retention-days {
width: 5ch;
text-align: right;
Expand Down
5 changes: 5 additions & 0 deletions static/swagger/zulip.yaml
Expand Up @@ -472,6 +472,8 @@ paths:
* `realm_message_content_edit_limit_seconds`:
* `realm_message_content_delete_limit_seconds`:
* `realm_name`:
* `realm_restricted_to_domain`:
Expand Down Expand Up @@ -1006,6 +1008,9 @@ definitions:
realm_message_content_edit_limit_seconds:
type: integer
format: int64
realm_message_content_delete_limit_seconds:
type: integer
format: int64
realm_name:
type: string
realm_restricted_to_domain:
Expand Down
13 changes: 13 additions & 0 deletions static/templates/settings/organization-settings-admin.handlebars
Expand Up @@ -50,6 +50,19 @@
</label>
</div>

<div class="input-group disableable {{#unless realm_allow_message_deleting}}control-label-disabled{{/unless}}">
<label for="id_realm_message_content_delete_limit_minutes"
id="id_realm_message_content_delete_limit_minutes_label"
title="{{t 'If non-zero, users can delete their message for this many minutes after it is sent. If zero, users can delete all their past messages.' }}">
{{t 'Message delete limit in minutes (0 for no limit)' }}
</label>
<input type="text" id="id_realm_message_content_delete_limit_minutes"
name="realm_message_content_delete_limit_minutes"
class="admin-realm-message-content-delete-limit-minutes"
value="{{ realm_message_content_delete_limit_minutes }}"
{{#unless realm_allow_message_deleting}}disabled="disabled"{{/unless}} />
</div>

<div class="input-group">
<label class="checkbox">
<input type="checkbox" id="id_realm_allow_edit_history" name="realm_allow_edit_history"
Expand Down
15 changes: 15 additions & 0 deletions zerver/lib/actions.py
Expand Up @@ -546,6 +546,21 @@ def do_set_realm_message_editing(realm: Realm,
)
send_event(event, active_user_ids(realm.id))

def do_set_realm_message_deleting(realm: Realm,
allow_message_deleting: bool,
message_content_delete_limit_seconds: int) -> None:
realm.allow_message_deleting = allow_message_deleting
realm.message_content_delete_limit_seconds = message_content_delete_limit_seconds
realm.save(update_fields=['allow_message_deleting', 'message_content_delete_limit_seconds'])
event = dict(
type="realm",
op="update_dict",
property="default",
data=dict(allow_message_deleting=allow_message_deleting,
message_content_delete_limit_seconds=message_content_delete_limit_seconds),
)
send_event(event, active_user_ids(realm.id))

def do_set_realm_notifications_stream(realm: Realm, stream: Stream, stream_id: int) -> None:
realm.notifications_stream = stream
realm.save(update_fields=['notifications_stream'])
Expand Down
2 changes: 2 additions & 0 deletions zerver/lib/events.py
Expand Up @@ -152,7 +152,9 @@ def fetch_initial_state_data(user_profile, event_types, queue_id, client_gravata
realm = user_profile.realm
state['realm_authentication_methods'] = realm.authentication_methods_dict()
state['realm_allow_message_editing'] = realm.allow_message_editing
state['realm_allow_message_deleting'] = realm.allow_message_deleting
state['realm_message_content_edit_limit_seconds'] = realm.message_content_edit_limit_seconds
state['realm_message_content_delete_limit_seconds'] = realm.message_content_delete_limit_seconds
state['realm_icon_url'] = realm_icon_url(realm)
state['realm_icon_source'] = realm.icon_source
state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
Expand Down
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-14 12:58
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('zerver', '0128_scheduledemail_realm'),
]

operations = [
migrations.AddField(
model_name='realm',
name='message_content_delete_limit_seconds',
field=models.IntegerField(default=120),
),
]
5 changes: 3 additions & 2 deletions zerver/models.py
Expand Up @@ -151,8 +151,10 @@ class Realm(models.Model):
description = models.TextField(null=True) # type: Optional[Text]

allow_message_deleting = models.BooleanField(default=False) # type: bool
DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS = 120 # if changed, also change in admin.js, setting_org.js
message_content_delete_limit_seconds = models.IntegerField(default=DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS) # type: int
allow_message_editing = models.BooleanField(default=True) # type: bool
DEFAULT_MESSAGE_CONTENT_EDIT_LIMIT_SECONDS = 600 # if changed, also change in admin.js
DEFAULT_MESSAGE_CONTENT_EDIT_LIMIT_SECONDS = 600 # if changed, also change in admin.js, setting_org.js
message_content_edit_limit_seconds = models.IntegerField(default=DEFAULT_MESSAGE_CONTENT_EDIT_LIMIT_SECONDS) # type: int
message_retention_days = models.IntegerField(null=True) # type: Optional[int]
allow_edit_history = models.BooleanField(default=True) # type: bool
Expand All @@ -177,7 +179,6 @@ class Realm(models.Model):
property_types = dict(
add_emoji_by_admins_only=bool,
allow_edit_history=bool,
allow_message_deleting=bool,
create_stream_by_admins_only=bool,
default_language=Text,
description=Text,
Expand Down
1 change: 1 addition & 0 deletions zerver/tests/test_home.py
Expand Up @@ -130,6 +130,7 @@ def test_home(self) -> None:
"realm_invite_required",
"realm_is_zephyr_mirror_realm",
"realm_mandatory_topics",
"realm_message_content_delete_limit_seconds",
"realm_message_content_edit_limit_seconds",
"realm_message_retention_days",
"realm_name",
Expand Down
33 changes: 25 additions & 8 deletions zerver/tests/test_messages.py
Expand Up @@ -2300,7 +2300,7 @@ def test_delete_message_by_owner(self) -> None:
self.login("hamlet@zulip.com")
msg_id = self.send_stream_message("hamlet@zulip.com", "Scotland")
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id))
self.assert_json_error(result, "You don't have permission to edit this message")
self.assert_json_error(result, "You don't have permission to delete this message")

def test_delete_message_by_realm_admin(self) -> None:
self.login("iago@zulip.com")
Expand All @@ -2318,21 +2318,38 @@ def test_delete_message_second_time(self) -> None:

def test_delete_message_by_user(self) -> None:

def change_allow_message_deleting_setting(value: bool) -> None:
def set_message_deleting_params(allow_message_deleting: bool,
message_content_delete_limit_seconds: int) -> None:
self.login("iago@zulip.com")
admin_user = self.example_user("iago")
admin_user.realm.allow_message_deleting = value
result = self.client_patch("/json/realm", {
'allow_message_deleting': ujson.dumps(allow_message_deleting),
'message_content_delete_limit_seconds': message_content_delete_limit_seconds
})
self.assert_json_success(result)
self.logout()

change_allow_message_deleting_setting(False)
self.login("hamlet@zulip.com")
self.login(self.example_email("hamlet"))
msg_id = self.send_stream_message("hamlet@zulip.com", "Scotland")
message = Message.objects.get(id=msg_id)
message.pub_date = message.pub_date - datetime.timedelta(seconds=180)
message.save()

set_message_deleting_params(False, 240)
self.login(self.example_email("hamlet"))
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id))
self.assert_json_error(result, "You don't have permission to edit this message")
self.assert_json_error(result, "You don't have permission to delete this message")

set_message_deleting_params(True, 120)
self.login(self.example_email("hamlet"))
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id))
self.assert_json_error(result, "The time limit for deleting this message has past")

change_allow_message_deleting_setting(True)
set_message_deleting_params(True, 240)
self.login(self.example_email("hamlet"))
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id))
self.assert_json_success(result)


class SoftDeactivationMessageTest(ZulipTestCase):

def test_maybe_catch_up_soft_deactivated_user(self) -> None:
Expand Down
12 changes: 12 additions & 0 deletions zerver/tests/test_realm.py
Expand Up @@ -329,3 +329,15 @@ def test_update_realm_allow_message_editing(self) -> None:
realm = self.update_with_api('message_content_edit_limit_seconds', 200)
self.assertEqual(realm.allow_message_editing, False)
self.assertEqual(realm.message_content_edit_limit_seconds, 200)

def test_update_realm_allow_message_deleting(self) -> None:
"""Tests updating the realm property 'allow_message_deleting'."""
self.set_up_db('allow_message_deleting', False)
self.set_up_db('message_content_delete_limit_seconds', 0)
realm = self.update_with_api('allow_message_deleting', True)
realm = self.update_with_api('message_content_delete_limit_seconds', 100)
self.assertEqual(realm.allow_message_deleting, True)
self.assertEqual(realm.message_content_delete_limit_seconds, 100)
realm = self.update_with_api('allow_message_deleting', False)
self.assertEqual(realm.allow_message_deleting, False)
self.assertEqual(realm.message_content_delete_limit_seconds, 100)

0 comments on commit 1fe7ad1

Please sign in to comment.