mirror of https://github.com/zulip/zulip.git
realm: Allow only owners to configure auth methods for a realm.
This commit adds the restriction on configuring auth methods for admins. We now allow only owners to configure the auth methods for realm.
This commit is contained in:
parent
a6f31c3668
commit
87e72ac8e2
|
@ -18,6 +18,9 @@ exports.maybe_disable_widgets = function () {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(".organization-box [data-name='auth-methods']")
|
||||||
|
.find("input, button, select, checked").attr("disabled", true);
|
||||||
|
|
||||||
if (page_params.is_admin) {
|
if (page_params.is_admin) {
|
||||||
$("#deactivate_realm_button").attr("disabled", true);
|
$("#deactivate_realm_button").attr("disabled", true);
|
||||||
return;
|
return;
|
||||||
|
@ -37,9 +40,6 @@ exports.maybe_disable_widgets = function () {
|
||||||
|
|
||||||
$(".organization-box [data-name='organization-permissions']")
|
$(".organization-box [data-name='organization-permissions']")
|
||||||
.find(".control-label-disabled").addClass('enabled');
|
.find(".control-label-disabled").addClass('enabled');
|
||||||
|
|
||||||
$(".organization-box [data-name='auth-methods']")
|
|
||||||
.find("input, button, select, checked").attr("disabled", true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.get_sorted_options_list = function (option_values_object) {
|
exports.get_sorted_options_list = function (option_values_object) {
|
||||||
|
@ -310,7 +310,7 @@ exports.populate_auth_methods = function (auth_methods) {
|
||||||
rendered_auth_method_rows += render_settings_admin_auth_methods_list({
|
rendered_auth_method_rows += render_settings_admin_auth_methods_list({
|
||||||
method: auth_method,
|
method: auth_method,
|
||||||
enabled: value,
|
enabled: value,
|
||||||
is_admin: page_params.is_admin,
|
is_owner: page_params.is_owner,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
auth_methods_table.html(rendered_auth_method_rows);
|
auth_methods_table.html(rendered_auth_method_rows);
|
||||||
|
@ -324,6 +324,7 @@ function insert_tip_box() {
|
||||||
$(".organization-box").find(".settings-section:not(.can-edit)")
|
$(".organization-box").find(".settings-section:not(.can-edit)")
|
||||||
.not("#emoji-settings")
|
.not("#emoji-settings")
|
||||||
.not("#user-groups-admin")
|
.not("#user-groups-admin")
|
||||||
|
.not("#organization-auth-settings")
|
||||||
.prepend(tip_box);
|
.prepend(tip_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<label class="checkbox">
|
<label class="checkbox">
|
||||||
<input type="checkbox" {{#if enabled}}checked="checked"{{/if}} {{#unless is_admin}}disabled{{/unless}}/>
|
<input type="checkbox" {{#if enabled}}checked="checked"{{/if}} {{#unless is_owner}}disabled{{/unless}}/>
|
||||||
<span></span>
|
<span></span>
|
||||||
</label>
|
</label>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
<div id="organization-auth-settings" class="settings-section" data-name="auth-methods">
|
<div id="organization-auth-settings" class="settings-section" data-name="auth-methods">
|
||||||
|
{{#unless is_owner}}
|
||||||
|
<div class='tip'>{{t "Only organization owners can edit these settings."}}</div>
|
||||||
|
{{/unless}}
|
||||||
<form class="form-horizontal admin-realm-form org-authentications-form">
|
<form class="form-horizontal admin-realm-form org-authentications-form">
|
||||||
<div id="org-auth_settings" class="admin-table-wrapper org-subsection-parent">
|
<div id="org-auth_settings" class="admin-table-wrapper org-subsection-parent">
|
||||||
<div class ="subsection-header">
|
<div class ="subsection-header">
|
||||||
|
|
|
@ -87,8 +87,8 @@
|
||||||
<li class="collapse-org-settings {% if not is_admin %}hide-org-settings{% endif %}" tabindex="0" data-section="auth-methods">
|
<li class="collapse-org-settings {% if not is_admin %}hide-org-settings{% endif %}" tabindex="0" data-section="auth-methods">
|
||||||
<i class="icon fa fa-key" aria-hidden="true"></i>
|
<i class="icon fa fa-key" aria-hidden="true"></i>
|
||||||
<div class="text">{{ _('Authentication methods') }}</div>
|
<div class="text">{{ _('Authentication methods') }}</div>
|
||||||
{% if not is_admin %}
|
{% if not is_owner %}
|
||||||
<i class="locked fa fa-lock" title="{{ _('Only organization administrators can edit these settings.') }}"></i>
|
<i class="locked fa fa-lock" title="{{ _('Only organization owners can edit these settings.') }}"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% if not is_guest %}
|
{% if not is_guest %}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Configure authentication methods
|
# Configure authentication methods
|
||||||
|
|
||||||
{!admin-only.md!}
|
{!owner-only.md!}
|
||||||
|
|
||||||
By default, Zulip allows logging in via email/password as well as
|
By default, Zulip allows logging in via email/password as well as
|
||||||
various social authentication providers like Google, GitHub, and
|
various social authentication providers like Google, GitHub, and
|
||||||
|
|
|
@ -4709,6 +4709,11 @@ class TestAdminSetBackends(ZulipTestCase):
|
||||||
def test_change_enabled_backends(self) -> None:
|
def test_change_enabled_backends(self) -> None:
|
||||||
# Log in as admin
|
# Log in as admin
|
||||||
self.login('iago')
|
self.login('iago')
|
||||||
|
result = self.client_patch("/json/realm", {
|
||||||
|
'authentication_methods': ujson.dumps({'Email': False, 'Dev': True})})
|
||||||
|
self.assert_json_error(result, 'Only organization owners can configure authentication methods.')
|
||||||
|
|
||||||
|
self.login('desdemona')
|
||||||
result = self.client_patch("/json/realm", {
|
result = self.client_patch("/json/realm", {
|
||||||
'authentication_methods': ujson.dumps({'Email': False, 'Dev': True})})
|
'authentication_methods': ujson.dumps({'Email': False, 'Dev': True})})
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
@ -4718,7 +4723,7 @@ class TestAdminSetBackends(ZulipTestCase):
|
||||||
|
|
||||||
def test_disable_all_backends(self) -> None:
|
def test_disable_all_backends(self) -> None:
|
||||||
# Log in as admin
|
# Log in as admin
|
||||||
self.login('iago')
|
self.login('desdemona')
|
||||||
result = self.client_patch("/json/realm", {
|
result = self.client_patch("/json/realm", {
|
||||||
'authentication_methods': ujson.dumps({'Email': False, 'Dev': False})})
|
'authentication_methods': ujson.dumps({'Email': False, 'Dev': False})})
|
||||||
self.assert_json_error(result, 'At least one authentication method must be enabled.')
|
self.assert_json_error(result, 'At least one authentication method must be enabled.')
|
||||||
|
@ -4728,7 +4733,7 @@ class TestAdminSetBackends(ZulipTestCase):
|
||||||
|
|
||||||
def test_supported_backends_only_updated(self) -> None:
|
def test_supported_backends_only_updated(self) -> None:
|
||||||
# Log in as admin
|
# Log in as admin
|
||||||
self.login('iago')
|
self.login('desdemona')
|
||||||
# Set some supported and unsupported backends
|
# Set some supported and unsupported backends
|
||||||
result = self.client_patch("/json/realm", {
|
result = self.client_patch("/json/realm", {
|
||||||
'authentication_methods': ujson.dumps({'Email': False, 'Dev': True, 'GitHub': False})})
|
'authentication_methods': ujson.dumps({'Email': False, 'Dev': True, 'GitHub': False})})
|
||||||
|
|
|
@ -312,12 +312,14 @@ def home_real(request: HttpRequest) -> HttpResponse:
|
||||||
if user_profile is not None:
|
if user_profile is not None:
|
||||||
night_mode = user_profile.night_mode
|
night_mode = user_profile.night_mode
|
||||||
is_guest = user_profile.is_guest
|
is_guest = user_profile.is_guest
|
||||||
|
is_realm_owner = user_profile.is_realm_owner
|
||||||
is_realm_admin = user_profile.is_realm_admin
|
is_realm_admin = user_profile.is_realm_admin
|
||||||
show_webathena = user_profile.realm.webathena_enabled
|
show_webathena = user_profile.realm.webathena_enabled
|
||||||
else: # nocoverage
|
else: # nocoverage
|
||||||
night_mode = False
|
night_mode = False
|
||||||
is_guest = False
|
is_guest = False
|
||||||
is_realm_admin = False
|
is_realm_admin = False
|
||||||
|
is_realm_owner = False
|
||||||
show_webathena = False
|
show_webathena = False
|
||||||
|
|
||||||
navbar_logo_url = compute_navbar_logo_url(page_params)
|
navbar_logo_url = compute_navbar_logo_url(page_params)
|
||||||
|
@ -332,6 +334,7 @@ def home_real(request: HttpRequest) -> HttpResponse:
|
||||||
'show_billing': show_billing,
|
'show_billing': show_billing,
|
||||||
'corporate_enabled': settings.CORPORATE_ENABLED,
|
'corporate_enabled': settings.CORPORATE_ENABLED,
|
||||||
'show_plans': show_plans,
|
'show_plans': show_plans,
|
||||||
|
'is_owner': is_realm_owner,
|
||||||
'is_admin': is_realm_admin,
|
'is_admin': is_realm_admin,
|
||||||
'is_guest': is_guest,
|
'is_guest': is_guest,
|
||||||
'night_mode': night_mode,
|
'night_mode': night_mode,
|
||||||
|
|
|
@ -98,8 +98,11 @@ def update_realm(
|
||||||
return json_error(_("Organization description is too long."))
|
return json_error(_("Organization description is too long."))
|
||||||
if name is not None and len(name) > Realm.MAX_REALM_NAME_LENGTH:
|
if name is not None and len(name) > Realm.MAX_REALM_NAME_LENGTH:
|
||||||
return json_error(_("Organization name is too long."))
|
return json_error(_("Organization name is too long."))
|
||||||
if authentication_methods is not None and True not in list(authentication_methods.values()):
|
if authentication_methods is not None:
|
||||||
return json_error(_("At least one authentication method must be enabled."))
|
if not user_profile.is_realm_owner:
|
||||||
|
return json_error(_("Only organization owners can configure authentication methods."))
|
||||||
|
if True not in list(authentication_methods.values()):
|
||||||
|
return json_error(_("At least one authentication method must be enabled."))
|
||||||
if (video_chat_provider is not None and
|
if (video_chat_provider is not None and
|
||||||
video_chat_provider not in {p['id'] for p in Realm.VIDEO_CHAT_PROVIDERS.values()}):
|
video_chat_provider not in {p['id'] for p in Realm.VIDEO_CHAT_PROVIDERS.values()}):
|
||||||
return json_error(_("Invalid video_chat_provider {}").format(video_chat_provider))
|
return json_error(_("Invalid video_chat_provider {}").format(video_chat_provider))
|
||||||
|
|
Loading…
Reference in New Issue