mirror of https://github.com/zulip/zulip.git
Add optional waiting period for users to create streams.
This adds support for only allowing normal users with account age equal or greater than a "waiting period" threshold to create streams; this is useful for open organizations that want new members to understand the community before creating streams. If create_stream_by_admins_only setting is set to True, only admin users were able to create streams. Now normal users with account age greater or equal than waiting period threshold can also create streams. Account age is defined as number of days passed since the user had created his account. Fixes: #2308. Tweaked by tabbott to clean up the actual can_create_streams logic and the tests.
This commit is contained in:
parent
e04fe084b7
commit
75bf501553
|
@ -274,7 +274,8 @@ function _setup_page() {
|
|||
realm_message_content_edit_limit_minutes:
|
||||
Math.ceil(page_params.realm_message_content_edit_limit_seconds / 60),
|
||||
language_list: page_params.language_list,
|
||||
realm_default_language: page_params.realm_default_language
|
||||
realm_default_language: page_params.realm_default_language,
|
||||
realm_waiting_period_threshold: page_params.realm_waiting_period_threshold
|
||||
};
|
||||
var admin_tab = templates.render('admin_tab', options);
|
||||
$("#administration").html(admin_tab);
|
||||
|
@ -287,6 +288,7 @@ function _setup_page() {
|
|||
$("#admin-realm-create-stream-by-admins-only-status").expectOne().hide();
|
||||
$("#admin-realm-message-editing-status").expectOne().hide();
|
||||
$("#admin-realm-default-language-status").expectOne().hide();
|
||||
$('#admin-realm-waiting_period_threshold_status').expectOne().hide();
|
||||
$("#admin-emoji-status").expectOne().hide();
|
||||
$('#admin-filter-status').expectOne().hide();
|
||||
$('#admin-filter-pattern-status').expectOne().hide();
|
||||
|
@ -499,6 +501,7 @@ function _setup_page() {
|
|||
var create_stream_by_admins_only_status = $("#admin-realm-create-stream-by-admins-only-status").expectOne();
|
||||
var message_editing_status = $("#admin-realm-message-editing-status").expectOne();
|
||||
var default_language_status = $("#admin-realm-default-language-status").expectOne();
|
||||
var waiting_period_threshold_status = $("#admin-realm-waiting_period_threshold_status").expectOne();
|
||||
name_status.hide();
|
||||
restricted_to_domain_status.hide();
|
||||
invite_required_status.hide();
|
||||
|
@ -519,6 +522,7 @@ function _setup_page() {
|
|||
var new_allow_message_editing = $("#id_realm_allow_message_editing").prop("checked");
|
||||
var new_message_content_edit_limit_minutes = $("#id_realm_message_content_edit_limit_minutes").val();
|
||||
var new_default_language = $("#id_realm_default_language").val();
|
||||
var new_waiting_period_threshold = $("#id_realm_waiting_period_threshold").val();
|
||||
var new_auth_methods = {};
|
||||
_.each($("#admin_auth_methods_table").find('tr.method_row'), function (method_row) {
|
||||
new_auth_methods[$(method_row).data('method')] = $(method_row).find('input').prop('checked');
|
||||
|
@ -547,7 +551,8 @@ function _setup_page() {
|
|||
allow_message_editing: JSON.stringify(new_allow_message_editing),
|
||||
message_content_edit_limit_seconds:
|
||||
JSON.stringify(parseInt(new_message_content_edit_limit_minutes, 10) * 60),
|
||||
default_language: JSON.stringify(new_default_language)
|
||||
default_language: JSON.stringify(new_default_language),
|
||||
waiting_period_threshold: JSON.stringify(parseInt(new_waiting_period_threshold, 10))
|
||||
};
|
||||
|
||||
channel.patch({
|
||||
|
@ -617,6 +622,11 @@ function _setup_page() {
|
|||
ui.report_success(i18n.t("Default language changed!"), default_language_status);
|
||||
}
|
||||
}
|
||||
if (response_data.waiting_period_threshold !== undefined) {
|
||||
if (response_data.waiting_period_threshold > 0) {
|
||||
ui.report_success(i18n.t("waiting period threshold changed!"), waiting_period_threshold_status);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
var reason = $.parseJSON(xhr.responseText).reason;
|
||||
|
|
|
@ -70,6 +70,8 @@ function dispatch_normal_event(event) {
|
|||
} else if (event.op === 'update' && event.property === 'default_language') {
|
||||
page_params.realm_default_language = event.value;
|
||||
admin.reset_realm_default_language();
|
||||
} else if (event.op === 'update' && event.property === 'waiting_period_threshold') {
|
||||
page_params.realm_waiting_period_threshold = event.value;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<div class="alert" id="admin-realm-create-stream-by-admins-only-status"></div>
|
||||
<div class="alert" id="admin-realm-message-editing-status"></div>
|
||||
<div class="alert" id="admin-realm-default-language-status"></div>
|
||||
<div class="alert" id="admin-realm-waiting_period_threshold_status"></div>
|
||||
|
||||
<div class="input-group admin-realm">
|
||||
<label for="realm_name">{{t "Your organization's name" }}</label>
|
||||
|
@ -83,6 +84,13 @@
|
|||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="realm_waiting_period_threshold">{{t "Waiting period for stream creation (in days)" }}</label>
|
||||
<input type="text" id="id_realm_waiting_period_threshold"
|
||||
name="realm_waiting_period_threshold"
|
||||
class="admin-realm-message-content-edit-limit-minutes"
|
||||
value="{{ realm_waiting_period_threshold }}"/>
|
||||
</div>
|
||||
<div class="input-group organization-submission">
|
||||
<input type="submit" class="button" value="{{t 'Save changes' }}" />
|
||||
</div>
|
||||
|
|
|
@ -564,6 +564,18 @@ def do_set_realm_default_language(realm, default_language):
|
|||
)
|
||||
send_event(event, active_user_ids(realm))
|
||||
|
||||
def do_set_realm_waiting_period_threshold(realm, threshold):
|
||||
# type: (Realm, int) -> None
|
||||
realm.waiting_period_threshold = threshold
|
||||
realm.save(update_fields=['waiting_period_threshold'])
|
||||
event = dict(
|
||||
type="realm",
|
||||
op="update",
|
||||
property='waiting_period_threshold',
|
||||
value=threshold,
|
||||
)
|
||||
send_event(event, active_user_ids(realm))
|
||||
|
||||
def do_deactivate_realm(realm):
|
||||
# type: (Realm) -> None
|
||||
"""
|
||||
|
@ -3046,6 +3058,7 @@ def fetch_initial_state_data(user_profile, event_types, queue_id):
|
|||
state['realm_allow_message_editing'] = user_profile.realm.allow_message_editing
|
||||
state['realm_message_content_edit_limit_seconds'] = user_profile.realm.message_content_edit_limit_seconds
|
||||
state['realm_default_language'] = user_profile.realm.default_language
|
||||
state['realm_waiting_period_threshold'] = user_profile.realm.waiting_period_threshold
|
||||
|
||||
if want('realm_domain'):
|
||||
state['realm_domain'] = user_profile.realm.domain
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('zerver', '0044_reaction'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='realm',
|
||||
name='waiting_period_threshold',
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
]
|
|
@ -136,6 +136,7 @@ class Realm(ModelReprMixin, models.Model):
|
|||
default_language = models.CharField(default=u'en', max_length=MAX_LANGUAGE_ID_LENGTH) # type: Text
|
||||
authentication_methods = BitField(flags=AUTHENTICATION_FLAGS,
|
||||
default=2**31 - 1) # type: BitHandler
|
||||
waiting_period_threshold = models.PositiveIntegerField(default=0) # type: int
|
||||
|
||||
DEFAULT_NOTIFICATION_STREAM_NAME = u'announce'
|
||||
|
||||
|
@ -604,9 +605,13 @@ class UserProfile(ModelReprMixin, AbstractBaseUser, PermissionsMixin):
|
|||
|
||||
def can_create_streams(self):
|
||||
# type: () -> bool
|
||||
if self.is_realm_admin or not self.realm.create_stream_by_admins_only:
|
||||
diff = (timezone.now() - self.date_joined).days
|
||||
if self.is_realm_admin:
|
||||
return True
|
||||
elif self.realm.create_stream_by_admins_only:
|
||||
return False
|
||||
if diff >= self.realm.waiting_period_threshold:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def major_tos_version(self):
|
||||
|
|
|
@ -35,7 +35,7 @@ from zerver.models import (
|
|||
)
|
||||
|
||||
from zerver.lib.actions import (
|
||||
do_add_default_stream, do_change_is_admin,
|
||||
do_add_default_stream, do_change_is_admin, do_set_realm_waiting_period_threshold,
|
||||
do_create_realm, do_remove_default_stream, do_set_realm_create_stream_by_admins_only,
|
||||
gather_subscriptions_helper, bulk_add_subscriptions, bulk_remove_subscriptions,
|
||||
gather_subscriptions, get_default_streams_for_realm, get_realm_by_string_id, get_stream,
|
||||
|
@ -557,15 +557,15 @@ class StreamAdminTest(ZulipTestCase):
|
|||
def test_create_stream_by_admins_only_setting(self):
|
||||
# type: () -> None
|
||||
"""
|
||||
When realm.create_stream_by_admins_only setting is active,
|
||||
non admin users shouldn't be able to create new streams.
|
||||
When realm.create_stream_by_admins_only setting is active and
|
||||
the number of days since the user had joined is less than waiting period
|
||||
threshold, non admin users shouldn't be able to create new streams.
|
||||
"""
|
||||
email = 'hamlet@zulip.com'
|
||||
self.login(email)
|
||||
user_profile = get_user_profile_by_email(email)
|
||||
do_change_is_admin(user_profile, False)
|
||||
|
||||
self.login(email)
|
||||
do_set_realm_create_stream_by_admins_only(user_profile.realm, True)
|
||||
|
||||
stream_name = ['adminsonlysetting']
|
||||
result = self.common_subscribe_to_streams(
|
||||
email,
|
||||
|
@ -573,8 +573,33 @@ class StreamAdminTest(ZulipTestCase):
|
|||
)
|
||||
self.assert_json_error(result, 'User cannot create streams.')
|
||||
|
||||
# Change setting back to default
|
||||
do_set_realm_create_stream_by_admins_only(user_profile.realm, False)
|
||||
def test_create_stream_by_waiting_period_threshold(self):
|
||||
# type: () -> None
|
||||
"""
|
||||
Non admin users with account age greater or equal to waiting period
|
||||
threshold should be able to create new streams.
|
||||
"""
|
||||
email = 'hamlet@zulip.com'
|
||||
user_profile = get_user_profile_by_email(email)
|
||||
self.login(email)
|
||||
do_change_is_admin(user_profile, False)
|
||||
|
||||
do_set_realm_waiting_period_threshold(user_profile.realm, 10)
|
||||
|
||||
stream_name = ['waitingperiodtest']
|
||||
result = self.common_subscribe_to_streams(
|
||||
email,
|
||||
stream_name
|
||||
)
|
||||
self.assert_json_error(result, 'User cannot create streams.')
|
||||
|
||||
do_set_realm_waiting_period_threshold(user_profile.realm, 0)
|
||||
|
||||
result = self.common_subscribe_to_streams(
|
||||
email,
|
||||
stream_name
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
|
||||
def test_remove_already_not_subbed(self):
|
||||
# type: () -> None
|
||||
|
|
|
@ -1887,6 +1887,7 @@ class HomeTest(ZulipTestCase):
|
|||
"realm_name",
|
||||
"realm_restricted_to_domain",
|
||||
"realm_uri",
|
||||
"realm_waiting_period_threshold",
|
||||
"referrals",
|
||||
"save_stacktraces",
|
||||
"server_generation",
|
||||
|
|
|
@ -591,6 +591,7 @@ def home_real(request):
|
|||
realm_message_content_edit_limit_seconds = register_ret['realm_message_content_edit_limit_seconds'],
|
||||
realm_restricted_to_domain = register_ret['realm_restricted_to_domain'],
|
||||
realm_default_language = register_ret['realm_default_language'],
|
||||
realm_waiting_period_threshold = register_ret['realm_waiting_period_threshold'],
|
||||
enter_sends = user_profile.enter_sends,
|
||||
user_id = user_profile.id,
|
||||
left_side_userlist = register_ret['left_side_userlist'],
|
||||
|
|
|
@ -13,6 +13,7 @@ from zerver.lib.actions import (
|
|||
do_set_realm_message_editing,
|
||||
do_set_realm_restricted_to_domain,
|
||||
do_set_realm_default_language,
|
||||
do_set_realm_waiting_period_threshold,
|
||||
do_set_realm_authentication_methods
|
||||
)
|
||||
from zerver.lib.i18n import get_available_language_codes
|
||||
|
@ -31,8 +32,9 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default
|
|||
allow_message_editing=REQ(validator=check_bool, default=None),
|
||||
message_content_edit_limit_seconds=REQ(converter=to_non_negative_int, default=None),
|
||||
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[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[int], Optional[str], Optional[dict]) -> HttpResponse
|
||||
# type: (HttpRequest, UserProfile, Optional[str], 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,)))
|
||||
|
@ -73,4 +75,7 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default
|
|||
if default_language is not None and realm.default_language != default_language:
|
||||
do_set_realm_default_language(realm, default_language)
|
||||
data['default_language'] = default_language
|
||||
if waiting_period_threshold is not None and realm.waiting_period_threshold != waiting_period_threshold:
|
||||
do_set_realm_waiting_period_threshold(realm, waiting_period_threshold)
|
||||
data['waiting_period_threshold'] = waiting_period_threshold
|
||||
return json_success(data)
|
||||
|
|
Loading…
Reference in New Issue