mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	admin: Enable admins to toggle supported auth methods via UI.
Add a table to the administration page that will allow realm admins to activate and deactivate the supported authentication methods for that realm.
This commit is contained in:
		@@ -529,6 +529,52 @@ casper.waitUntilVisible('#admin-realm-default-language-status', function () {
 | 
			
		||||
    casper.test.assertSelectorHasText('#admin-realm-default-language-status', 'Default language changed!');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Test authentication methods setting
 | 
			
		||||
casper.waitForSelector('input[type="checkbox"]', function () {
 | 
			
		||||
    casper.click(".method_row[data-method='Email'] input[type='checkbox']");
 | 
			
		||||
    casper.click('form.admin-realm-form input.button');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Test setting was activated--default is checked
 | 
			
		||||
casper.then(function () {
 | 
			
		||||
    // Scroll to bottom so that casper snapshots show the auth methods table
 | 
			
		||||
    this.scrollToBottom();
 | 
			
		||||
    // Test setting was activated
 | 
			
		||||
    casper.waitUntilVisible('#admin-realm-authentication-methods-status', function () {
 | 
			
		||||
        casper.test.assertSelectorHasText('#admin-realm-authentication-methods-status', 'Authentication methods saved!');
 | 
			
		||||
        casper.test.assertEval(function () {
 | 
			
		||||
            return !(document.querySelector(".method_row[data-method='Email'] input[type='checkbox']").checked);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
casper.then(function () {
 | 
			
		||||
    // Leave the page and return
 | 
			
		||||
    casper.click('#settings-dropdown');
 | 
			
		||||
    casper.click('a[href^="#subscriptions"]');
 | 
			
		||||
    casper.click('#settings-dropdown');
 | 
			
		||||
    casper.click('a[href^="#administration"]');
 | 
			
		||||
 | 
			
		||||
    casper.waitForSelector(".method_row[data-method='Email'] input[type='checkbox']", function () {
 | 
			
		||||
        // Test Setting was saved
 | 
			
		||||
        casper.test.assertEval(function () {
 | 
			
		||||
            return !(document.querySelector(".method_row[data-method='Email'] input[type='checkbox']").checked);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Deactivate setting--default is checked
 | 
			
		||||
casper.then(function () {
 | 
			
		||||
    casper.click(".method_row[data-method='Email'] input[type='checkbox']");
 | 
			
		||||
    casper.click('form.admin-realm-form input.button');
 | 
			
		||||
    casper.waitUntilVisible('#admin-realm-authentication-methods-status', function () {
 | 
			
		||||
        casper.test.assertSelectorHasText('#admin-realm-authentication-methods-status', 'Authentication methods saved!');
 | 
			
		||||
        casper.test.assertEval(function () {
 | 
			
		||||
            return document.querySelector(".method_row[data-method='Email'] input[type='checkbox']").checked;
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
common.then_log_out();
 | 
			
		||||
 | 
			
		||||
casper.run(function () {
 | 
			
		||||
 
 | 
			
		||||
@@ -216,6 +216,26 @@ function render(template_name, args) {
 | 
			
		||||
    assert.equal(count.text(), 99);
 | 
			
		||||
}());
 | 
			
		||||
 | 
			
		||||
(function admin_auth_methods_list() {
 | 
			
		||||
    var args = {
 | 
			
		||||
        method: {
 | 
			
		||||
            "method": "Email",
 | 
			
		||||
            "enabled": false
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    var html = '';
 | 
			
		||||
    html += '<tbody id="admin_auth_methods_table">';
 | 
			
		||||
    html += render('admin_auth_methods_list', args);
 | 
			
		||||
    html += '</tbody>';
 | 
			
		||||
 | 
			
		||||
    global.write_test_output('admin_auth_methods_list.handlebars', html);
 | 
			
		||||
 | 
			
		||||
    var method = $(html).find('tr.method_row:first span.method');
 | 
			
		||||
    assert.equal(method.text(), 'Email');
 | 
			
		||||
    assert.equal(method.is("checked"), false);
 | 
			
		||||
}());
 | 
			
		||||
 | 
			
		||||
(function bookend() {
 | 
			
		||||
    // Do subscribed/unsubscribed cases here.
 | 
			
		||||
    var args = {
 | 
			
		||||
 
 | 
			
		||||
@@ -174,6 +174,20 @@ exports.reset_realm_default_language = function () {
 | 
			
		||||
    $("#id_realm_default_language").val(page_params.realm_default_language);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.populate_auth_methods = function (auth_methods) {
 | 
			
		||||
    var auth_methods_table = $("#admin_auth_methods_table").expectOne();
 | 
			
		||||
    auth_methods_table.find('tr.method_row').remove();
 | 
			
		||||
    _.each(_.keys(auth_methods).sort(), function (key) {
 | 
			
		||||
        auth_methods_table.append(templates.render('admin_auth_methods_list', {
 | 
			
		||||
            method: {
 | 
			
		||||
                method: key,
 | 
			
		||||
                enabled: auth_methods[key]
 | 
			
		||||
            }
 | 
			
		||||
        }));
 | 
			
		||||
    });
 | 
			
		||||
    loading.destroy_indicator($('#admin_page_auth_methods_loading_indicator'));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function _setup_page() {
 | 
			
		||||
    var domains_string = stringify_list_with_conjunction(page_params.domains, "or");
 | 
			
		||||
    var atdomains = page_params.domains.slice();
 | 
			
		||||
@@ -189,6 +203,7 @@ 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_authentication_methods: page_params.realm_authentication_methods,
 | 
			
		||||
        realm_create_stream_by_admins_only: page_params.realm_create_stream_by_admins_only,
 | 
			
		||||
        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),
 | 
			
		||||
@@ -202,6 +217,7 @@ function _setup_page() {
 | 
			
		||||
    $("#admin-realm-restricted-to-domain-status").expectOne().hide();
 | 
			
		||||
    $("#admin-realm-invite-required-status").expectOne().hide();
 | 
			
		||||
    $("#admin-realm-invite-by-admins-only-status").expectOne().hide();
 | 
			
		||||
    $("#admin-realm-authentication-methods-status").expectOne().hide();
 | 
			
		||||
    $("#admin-realm-create-stream-by-admins-only-status").expectOne().hide();
 | 
			
		||||
    $("#admin-realm-message-editing-status").expectOne().hide();
 | 
			
		||||
    $("#admin-realm-default-language-status").expectOne().hide();
 | 
			
		||||
@@ -215,6 +231,7 @@ function _setup_page() {
 | 
			
		||||
    loading.make_indicator($('#admin_page_streams_loading_indicator'));
 | 
			
		||||
    loading.make_indicator($('#admin_page_deactivated_users_loading_indicator'));
 | 
			
		||||
    loading.make_indicator($('#admin_page_emoji_loading_indicator'));
 | 
			
		||||
    loading.make_indicator($('#admin_page_auth_methods_loading_indicator'));
 | 
			
		||||
 | 
			
		||||
    // Populate users and bots tables
 | 
			
		||||
    channel.get({
 | 
			
		||||
@@ -234,6 +251,9 @@ function _setup_page() {
 | 
			
		||||
        error: failed_listing_streams
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Populate authentication methods table
 | 
			
		||||
    exports.populate_auth_methods(page_params.realm_authentication_methods);
 | 
			
		||||
 | 
			
		||||
    // Populate emoji table
 | 
			
		||||
    exports.populate_emoji(page_params.realm_emoji);
 | 
			
		||||
    exports.update_default_streams_table();
 | 
			
		||||
@@ -406,14 +426,16 @@ 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 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 message_editing_status = $("#admin-realm-message-editing-status").expectOne();
 | 
			
		||||
        var default_language_status = $("#admin-realm-default-language-status").expectOne();
 | 
			
		||||
 | 
			
		||||
        var auth_methods_table = $('.admin_auth_methods_table');
 | 
			
		||||
        name_status.hide();
 | 
			
		||||
        restricted_to_domain_status.hide();
 | 
			
		||||
        invite_required_status.hide();
 | 
			
		||||
        invite_by_admins_only_status.hide();
 | 
			
		||||
        authentication_methods_status.hide();
 | 
			
		||||
        create_stream_by_admins_only_status.hide();
 | 
			
		||||
        message_editing_status.hide();
 | 
			
		||||
        default_language_status.hide();
 | 
			
		||||
@@ -429,7 +451,10 @@ 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_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');
 | 
			
		||||
        });
 | 
			
		||||
        // 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
 | 
			
		||||
@@ -448,6 +473,7 @@ 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),
 | 
			
		||||
            authentication_methods: JSON.stringify(new_auth_methods),
 | 
			
		||||
            create_stream_by_admins_only: JSON.stringify(new_create_stream_by_admins_only),
 | 
			
		||||
            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),
 | 
			
		||||
@@ -489,6 +515,11 @@ function _setup_page() {
 | 
			
		||||
                        ui.report_success(i18n.t("Any user may now create new streams!"), create_stream_by_admins_only_status);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (response_data.authentication_methods !== undefined) {
 | 
			
		||||
                    if (response_data.authentication_methods) {
 | 
			
		||||
                        ui.report_success(i18n.t("Authentication methods saved!"), authentication_methods_status);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (response_data.allow_message_editing !== undefined) {
 | 
			
		||||
                    // We expect message_content_edit_limit_seconds was sent in the
 | 
			
		||||
                    // response as well
 | 
			
		||||
@@ -515,8 +546,13 @@ function _setup_page() {
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            error: function (xhr, error) {
 | 
			
		||||
                var reason = $.parseJSON(xhr.responseText).reason;
 | 
			
		||||
                if (reason === "no authentication") {
 | 
			
		||||
                    ui.report_error(i18n.t("Failed!"), xhr, authentication_methods_status);
 | 
			
		||||
                } else {
 | 
			
		||||
                    ui.report_error(i18n.t("Failed!"), xhr, name_status);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,9 @@ function dispatch_normal_event(event) {
 | 
			
		||||
            $.each(event.data, function (key, value) {
 | 
			
		||||
                page_params['realm_' + key] = value;
 | 
			
		||||
            });
 | 
			
		||||
            if (event.data.authentication_methods !== undefined) {
 | 
			
		||||
                admin.populate_auth_methods(event.data.authentication_methods);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (event.op === 'update' && event.property === 'default_language') {
 | 
			
		||||
            page_params.realm_default_language = event.value;
 | 
			
		||||
            admin.reset_realm_default_language();
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@
 | 
			
		||||
  "Pin stream to top<br /> of left sidebar": "Pin stream to top<br /> of left sidebar", 
 | 
			
		||||
  "Password": "Password", 
 | 
			
		||||
  "Any user may now invite new users!": "Any user may now invite new users!",
 | 
			
		||||
  "Authentication methods saved!":"Authentication methods saved!",
 | 
			
		||||
  "Receive desktop <br />notifications": "Receive desktop <br />notifications", 
 | 
			
		||||
  "Please specify a stream": "Please specify a stream", 
 | 
			
		||||
  "Delete Alert Word": "Delete Alert Word", 
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
        <div role="tabpanel" class="tab-pane active" id="organization">
 | 
			
		||||
          {{ partial "organization-settings-admin" }}
 | 
			
		||||
          {{ partial "emoji-settings-admin" }}
 | 
			
		||||
          {{ partial "auth-methods-settings-admin" }}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div role="tabpanel" class="tab-pane" id="users">
 | 
			
		||||
          {{ partial "user-list-admin" }}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								static/templates/auth-methods-settings-admin.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								static/templates/auth-methods-settings-admin.handlebars
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<div id="organization-settings" class="settings-section">
 | 
			
		||||
    <div class="settings-section-title"><i class="icon-vector-lock settings-section-icon"></i>
 | 
			
		||||
        {{t "Authentication Methods" }}</div>
 | 
			
		||||
  <form class="form-horizontal admin-realm-form">
 | 
			
		||||
       <div class="alert" id="admin-realm-authentication-methods-status"></div>
 | 
			
		||||
        <div class="admin-table-wrapper">
 | 
			
		||||
          <p>{{#tr this}}Configure the authentication methods for the __domain__ organization.{{/tr}}</p>
 | 
			
		||||
          <table class="table table-condensed table-striped">
 | 
			
		||||
            <tbody id="admin_auth_methods_table" class=" admin_auth_methods_table">
 | 
			
		||||
              <th>{{t "Method" }}</th>
 | 
			
		||||
              <th>{{t "Enabled" }}</th>
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div id="admin_page_auth_methods_loading_indicator"></div>
 | 
			
		||||
        <div class="input-group">
 | 
			
		||||
            <div class="organization-submission">
 | 
			
		||||
                <input type="submit" class="button" value="{{t 'Save changes' }}" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
  </form>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										11
									
								
								static/templates/settings/admin_auth_methods_list.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								static/templates/settings/admin_auth_methods_list.handlebars
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
{{#with method}}
 | 
			
		||||
<tr class="method_row" data-method="{{method}}">
 | 
			
		||||
  <td>
 | 
			
		||||
    <span class="method">{{method}}</span>
 | 
			
		||||
  </td>
 | 
			
		||||
  <td>
 | 
			
		||||
  <input type="checkbox"
 | 
			
		||||
    {{#if enabled}}checked="checked"{{/if}} />
 | 
			
		||||
  </td>
 | 
			
		||||
</tr>
 | 
			
		||||
{{/with}}
 | 
			
		||||
@@ -437,6 +437,20 @@ def do_set_realm_invite_by_admins_only(realm, invite_by_admins_only):
 | 
			
		||||
    )
 | 
			
		||||
    send_event(event, active_user_ids(realm))
 | 
			
		||||
 | 
			
		||||
def do_set_realm_authentication_methods(realm, authentication_methods):
 | 
			
		||||
    # type: (Realm, Dict[str, bool]) -> None
 | 
			
		||||
    for key, value in list(authentication_methods.items()):
 | 
			
		||||
        index = getattr(realm.authentication_methods, key).number
 | 
			
		||||
        realm.authentication_methods.set_bit(index, int(value))
 | 
			
		||||
    realm.save(update_fields=['authentication_methods'])
 | 
			
		||||
    event = dict(
 | 
			
		||||
        type="realm",
 | 
			
		||||
        op="update_dict",
 | 
			
		||||
        property='default',
 | 
			
		||||
        data=dict(authentication_methods=realm.authentication_methods_dict())
 | 
			
		||||
    )
 | 
			
		||||
    send_event(event, active_user_ids(realm))
 | 
			
		||||
 | 
			
		||||
def do_set_realm_create_stream_by_admins_only(realm, create_stream_by_admins_only):
 | 
			
		||||
    # type: (Realm, bool) -> None
 | 
			
		||||
    realm.create_stream_by_admins_only = create_stream_by_admins_only
 | 
			
		||||
@@ -2842,6 +2856,7 @@ def fetch_initial_state_data(user_profile, event_types, queue_id):
 | 
			
		||||
        state['realm_restricted_to_domain'] = user_profile.realm.restricted_to_domain
 | 
			
		||||
        state['realm_invite_required'] = user_profile.realm.invite_required
 | 
			
		||||
        state['realm_invite_by_admins_only'] = user_profile.realm.invite_by_admins_only
 | 
			
		||||
        state['realm_authentication_methods'] = user_profile.realm.authentication_methods_dict()
 | 
			
		||||
        state['realm_create_stream_by_admins_only'] = user_profile.realm.create_stream_by_admins_only
 | 
			
		||||
        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
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ from confirmation.models import Confirmation
 | 
			
		||||
from zproject.backends import ZulipDummyBackend, EmailAuthBackend, \
 | 
			
		||||
    GoogleMobileOauth2Backend, ZulipRemoteUserBackend, ZulipLDAPAuthBackend, \
 | 
			
		||||
    ZulipLDAPUserPopulator, DevAuthBackend, GitHubAuthBackend, ZulipAuthMixin, \
 | 
			
		||||
    password_auth_enabled, github_auth_enabled, AUTH_BACKEND_NAME_MAP
 | 
			
		||||
    dev_auth_enabled, password_auth_enabled, github_auth_enabled, AUTH_BACKEND_NAME_MAP
 | 
			
		||||
 | 
			
		||||
from zerver.views.auth import maybe_send_to_registration
 | 
			
		||||
 | 
			
		||||
@@ -1444,3 +1444,41 @@ class TestMaybeSendToRegistration(ZulipTestCase):
 | 
			
		||||
                confirmation_key = confirmation.confirmation_key
 | 
			
		||||
                self.assertIn('do_confirm/' + confirmation_key, result.url)
 | 
			
		||||
                self.assertEqual(PreregistrationUser.objects.all().count(), 1)
 | 
			
		||||
 | 
			
		||||
class TestAdminSetBackends(ZulipTestCase):
 | 
			
		||||
 | 
			
		||||
    def test_change_enabled_backends(self):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        # Log in as admin
 | 
			
		||||
        self.login("iago@zulip.com")
 | 
			
		||||
        result = self.client_patch("/json/realm", {
 | 
			
		||||
            'authentication_methods': ujson.dumps({u'Email': False, u'Dev': True})})
 | 
			
		||||
        self.assert_json_success(result)
 | 
			
		||||
        realm = get_realm('zulip.com')
 | 
			
		||||
        self.assertFalse(password_auth_enabled(realm))
 | 
			
		||||
        self.assertTrue(dev_auth_enabled())
 | 
			
		||||
 | 
			
		||||
    def test_disable_all_backends(self):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        # Log in as admin
 | 
			
		||||
        self.login("iago@zulip.com")
 | 
			
		||||
        result = self.client_patch("/json/realm", {
 | 
			
		||||
            'authentication_methods' : ujson.dumps({u'Email': False, u'Dev': False})})
 | 
			
		||||
        self.assert_json_error(result, 'At least one authentication method must be enabled.', status_code=403)
 | 
			
		||||
        realm = get_realm('zulip.com')
 | 
			
		||||
        self.assertTrue(password_auth_enabled(realm))
 | 
			
		||||
        self.assertTrue(dev_auth_enabled())
 | 
			
		||||
 | 
			
		||||
    def test_supported_backends_only_updated(self):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        # Log in as admin
 | 
			
		||||
        self.login("iago@zulip.com")
 | 
			
		||||
        # Set some supported and unsupported backends
 | 
			
		||||
        result = self.client_patch("/json/realm", {
 | 
			
		||||
            'authentication_methods' : ujson.dumps({u'Email': False, u'Dev': True, u'GitHub': False})})
 | 
			
		||||
        self.assert_json_success(result)
 | 
			
		||||
        realm = get_realm('zulip.com')
 | 
			
		||||
        # Check that unsupported backend is not enabled
 | 
			
		||||
        self.assertFalse(github_auth_enabled(realm))
 | 
			
		||||
        self.assertTrue(dev_auth_enabled())
 | 
			
		||||
        self.assertFalse(password_auth_enabled(realm))
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,7 @@ from zerver.lib.actions import (
 | 
			
		||||
    do_set_realm_invite_by_admins_only,
 | 
			
		||||
    do_set_realm_message_editing,
 | 
			
		||||
    do_set_realm_default_language,
 | 
			
		||||
    do_set_realm_authentication_methods,
 | 
			
		||||
    do_update_message,
 | 
			
		||||
    do_update_pointer,
 | 
			
		||||
    do_change_twenty_four_hour_time,
 | 
			
		||||
@@ -466,6 +467,28 @@ class EventsRegisterTest(ZulipTestCase):
 | 
			
		||||
            error = schema_checker('events[0]', events[0])
 | 
			
		||||
            self.assert_on_error(error)
 | 
			
		||||
 | 
			
		||||
    def test_change_realm_authentication_methods(self):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        schema_checker = check_dict([
 | 
			
		||||
            ('type', equals('realm')),
 | 
			
		||||
            ('op', equals('update_dict')),
 | 
			
		||||
            ('property', equals('default')),
 | 
			
		||||
            ('data', check_dict([])),
 | 
			
		||||
        ])
 | 
			
		||||
        # Test transitions; any new backends should be tested with T/T/T/F/T
 | 
			
		||||
        for (auth_method_dict) in \
 | 
			
		||||
                ({'Google': True, 'Email': True, 'GitHub': True, 'LDAP': False, 'Dev': False},
 | 
			
		||||
                {'Google': True, 'Email': True, 'GitHub': False, 'LDAP': False, 'Dev': False},
 | 
			
		||||
                {'Google': True, 'Email': False, 'GitHub': False, 'LDAP': False, 'Dev': False},
 | 
			
		||||
                {'Google': True, 'Email': False, 'GitHub': True, 'LDAP': False, 'Dev': False },
 | 
			
		||||
                {'Google': False, 'Email': False, 'GitHub': False, 'LDAP': False, 'Dev': True},
 | 
			
		||||
                {'Google': False, 'Email': False, 'GitHub': True, 'LDAP': False, 'Dev': True},
 | 
			
		||||
                {'Google': False, 'Email': True, 'GitHub': True, 'LDAP': True, 'Dev': False}):
 | 
			
		||||
            events = self.do_test(lambda: do_set_realm_authentication_methods(self.user_profile.realm,
 | 
			
		||||
                                                                              auth_method_dict))
 | 
			
		||||
            error = schema_checker('events[0]', events[0])
 | 
			
		||||
            self.assert_on_error(error)
 | 
			
		||||
 | 
			
		||||
    def test_change_realm_invite_by_admins_only(self):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        schema_checker = check_dict([
 | 
			
		||||
 
 | 
			
		||||
@@ -1825,6 +1825,7 @@ class HomeTest(ZulipTestCase):
 | 
			
		||||
            "product_name",
 | 
			
		||||
            "prompt_for_invites",
 | 
			
		||||
            "realm_allow_message_editing",
 | 
			
		||||
            "realm_authentication_methods",
 | 
			
		||||
            "realm_create_stream_by_admins_only",
 | 
			
		||||
            "realm_default_language",
 | 
			
		||||
            "realm_default_streams",
 | 
			
		||||
 
 | 
			
		||||
@@ -581,6 +581,7 @@ def home(request):
 | 
			
		||||
        realm_name            = register_ret['realm_name'],
 | 
			
		||||
        realm_invite_required = register_ret['realm_invite_required'],
 | 
			
		||||
        realm_invite_by_admins_only = register_ret['realm_invite_by_admins_only'],
 | 
			
		||||
        realm_authentication_methods = register_ret['realm_authentication_methods'],
 | 
			
		||||
        realm_create_stream_by_admins_only = register_ret['realm_create_stream_by_admins_only'],
 | 
			
		||||
        realm_allow_message_editing = register_ret['realm_allow_message_editing'],
 | 
			
		||||
        realm_message_content_edit_limit_seconds = register_ret['realm_message_content_edit_limit_seconds'],
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
from __future__ import absolute_import
 | 
			
		||||
 | 
			
		||||
from typing import Any, Optional
 | 
			
		||||
 | 
			
		||||
from django.http import HttpRequest, HttpResponse
 | 
			
		||||
from django.utils.translation import ugettext as _
 | 
			
		||||
 | 
			
		||||
@@ -14,11 +13,12 @@ from zerver.lib.actions import (
 | 
			
		||||
    do_set_realm_message_editing,
 | 
			
		||||
    do_set_realm_restricted_to_domain,
 | 
			
		||||
    do_set_realm_default_language,
 | 
			
		||||
    do_set_realm_authentication_methods
 | 
			
		||||
)
 | 
			
		||||
from zerver.lib.i18n import get_available_language_codes
 | 
			
		||||
from zerver.lib.request import has_request_variables, REQ, JsonableError
 | 
			
		||||
from zerver.lib.response import json_success, json_error
 | 
			
		||||
from zerver.lib.validator import check_string, check_list, check_bool
 | 
			
		||||
from zerver.lib.validator import check_string, check_dict, check_bool
 | 
			
		||||
from zerver.models import UserProfile
 | 
			
		||||
 | 
			
		||||
@require_realm_admin
 | 
			
		||||
@@ -30,12 +30,12 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default
 | 
			
		||||
                 create_stream_by_admins_only=REQ(validator=check_bool, default=None),
 | 
			
		||||
                 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)):
 | 
			
		||||
    # type: (HttpRequest, UserProfile, Optional[str], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[int], Optional[str]) -> HttpResponse
 | 
			
		||||
                 default_language=REQ(validator=check_string, 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
 | 
			
		||||
    # 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,)))
 | 
			
		||||
 | 
			
		||||
    realm = user_profile.realm
 | 
			
		||||
    data = {} # type: Dict[str, Any]
 | 
			
		||||
    if name is not None and realm.name != name:
 | 
			
		||||
@@ -50,6 +50,13 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default
 | 
			
		||||
    if invite_by_admins_only is not None and realm.invite_by_admins_only != invite_by_admins_only:
 | 
			
		||||
        do_set_realm_invite_by_admins_only(realm, invite_by_admins_only)
 | 
			
		||||
        data['invite_by_admins_only'] = invite_by_admins_only
 | 
			
		||||
    if authentication_methods is not None and realm.authentication_methods != authentication_methods:
 | 
			
		||||
        if True not in list(authentication_methods.values()):
 | 
			
		||||
            return json_error(_("At least one authentication method must be enabled."),
 | 
			
		||||
                              data={"reason": "no authentication"}, status=403)
 | 
			
		||||
        else:
 | 
			
		||||
            do_set_realm_authentication_methods(realm, authentication_methods)
 | 
			
		||||
        data['authentication_methods'] = authentication_methods
 | 
			
		||||
    if create_stream_by_admins_only is not None and realm.create_stream_by_admins_only != create_stream_by_admins_only:
 | 
			
		||||
        do_set_realm_create_stream_by_admins_only(realm, create_stream_by_admins_only)
 | 
			
		||||
        data['create_stream_by_admins_only'] = create_stream_by_admins_only
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user