aboutsummaryrefslogtreecommitdiffstats
path: root/apps/settings/src/components/AdminTwoFactor.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/settings/src/components/AdminTwoFactor.vue')
-rw-r--r--apps/settings/src/components/AdminTwoFactor.vue98
1 files changed, 58 insertions, 40 deletions
diff --git a/apps/settings/src/components/AdminTwoFactor.vue b/apps/settings/src/components/AdminTwoFactor.vue
index ea9d6f97fde..e24bee02593 100644
--- a/apps/settings/src/components/AdminTwoFactor.vue
+++ b/apps/settings/src/components/AdminTwoFactor.vue
@@ -1,80 +1,94 @@
+<!--
+ - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
<template>
- <div>
- <p class="settings-hint">
- {{ t('settings', 'Two-factor authentication can be enforced for all users and specific groups. If they do not have a two-factor provider configured, they will be unable to log into the system.') }}
- </p>
+ <NcSettingsSection :name="t('settings', 'Two-Factor Authentication')"
+ :description="t('settings', 'Two-factor authentication can be enforced for all accounts and specific groups. If they do not have a two-factor provider configured, they will be unable to log into the system.')"
+ :doc-url="twoFactorAdminDoc">
<p v-if="loading">
<span class="icon-loading-small two-factor-loading" />
<span>{{ t('settings', 'Enforce two-factor authentication') }}</span>
</p>
- <p v-else>
- <input id="two-factor-enforced"
- v-model="enforced"
- type="checkbox"
- class="checkbox">
- <label for="two-factor-enforced">{{ t('settings', 'Enforce two-factor authentication') }}</label>
- </p>
+ <NcCheckboxRadioSwitch v-else
+ id="two-factor-enforced"
+ :checked.sync="enforced"
+ type="switch">
+ {{ t('settings', 'Enforce two-factor authentication') }}
+ </NcCheckboxRadioSwitch>
<template v-if="enforced">
<h3>{{ t('settings', 'Limit to groups') }}</h3>
{{ t('settings', 'Enforcement of two-factor authentication can be set for certain groups only.') }}
- <p>
+ <p class="top-margin">
{{ t('settings', 'Two-factor authentication is enforced for all members of the following groups.') }}
</p>
<p>
- <Multiselect v-model="enforcedGroups"
+ <label for="enforcedGroups">
+ <span>{{ t('settings', 'Enforced groups') }}</span>
+ </label>
+ <NcSelect v-model="enforcedGroups"
+ input-id="enforcedGroups"
:options="groups"
- :placeholder="t('settings', 'Enforced groups')"
:disabled="loading"
:multiple="true"
- :searchable="true"
:loading="loadingGroups"
- :show-no-options="false"
:close-on-select="false"
- @search-change="searchGroup" />
+ @search="searchGroup" />
</p>
- <p>
+ <p class="top-margin">
{{ t('settings', 'Two-factor authentication is not enforced for members of the following groups.') }}
</p>
<p>
- <Multiselect v-model="excludedGroups"
+ <label for="excludedGroups">
+ <span>{{ t('settings', 'Excluded groups') }}</span>
+ </label>
+ <NcSelect v-model="excludedGroups"
+ input-id="excludedGroups"
:options="groups"
- :placeholder="t('settings', 'Excluded groups')"
:disabled="loading"
:multiple="true"
- :searchable="true"
:loading="loadingGroups"
- :show-no-options="false"
:close-on-select="false"
- @search-change="searchGroup" />
+ @search="searchGroup" />
</p>
- <p>
+ <p class="top-margin">
<em>
<!-- this text is also found in the documentation. update it there as well if it ever changes -->
- {{ t('settings', 'When groups are selected/excluded, they use the following logic to determine if a user has 2FA enforced: If no groups are selected, 2FA is enabled for everyone except members of the excluded groups. If groups are selected, 2FA is enabled for all members of these. If a user is both in a selected and excluded group, the selected takes precedence and 2FA is enforced.') }}
+ {{ t('settings', 'When groups are selected/excluded, they use the following logic to determine if an account has 2FA enforced: If no groups are selected, 2FA is enabled for everyone except members of the excluded groups. If groups are selected, 2FA is enabled for all members of these. If an account is both in a selected and excluded group, the selected takes precedence and 2FA is enforced.') }}
</em>
</p>
</template>
- <p>
- <button v-if="dirty"
- class="button primary"
+ <p class="top-margin">
+ <NcButton v-if="dirty"
+ type="primary"
:disabled="loading"
@click="saveChanges">
{{ t('settings', 'Save changes') }}
- </button>
+ </NcButton>
</p>
- </div>
+ </NcSettingsSection>
</template>
<script>
import axios from '@nextcloud/axios'
-import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
-import _ from 'lodash'
+import NcSelect from '@nextcloud/vue/components/NcSelect'
+import NcButton from '@nextcloud/vue/components/NcButton'
+import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
+import NcSettingsSection from '@nextcloud/vue/components/NcSettingsSection'
+import { loadState } from '@nextcloud/initial-state'
+
+import sortedUniq from 'lodash/sortedUniq.js'
+import uniq from 'lodash/uniq.js'
+import debounce from 'lodash/debounce.js'
import { generateUrl, generateOcsUrl } from '@nextcloud/router'
export default {
name: 'AdminTwoFactor',
components: {
- Multiselect,
+ NcSelect,
+ NcButton,
+ NcCheckboxRadioSwitch,
+ NcSettingsSection,
},
data() {
return {
@@ -82,6 +96,7 @@ export default {
dirty: false,
groups: [],
loadingGroups: false,
+ twoFactorAdminDoc: loadState('settings', 'two-factor-admin-doc'),
}
},
computed: {
@@ -116,19 +131,19 @@ export default {
mounted() {
// Groups are loaded dynamically, but the assigned ones *should*
// be valid groups, so let's add them as initial state
- this.groups = _.sortedUniq(_.uniq(this.enforcedGroups.concat(this.excludedGroups)))
+ this.groups = sortedUniq(uniq(this.enforcedGroups.concat(this.excludedGroups)))
// Populate the groups with a first set so the dropdown is not empty
// when opening the page the first time
this.searchGroup('')
},
methods: {
- searchGroup: _.debounce(function(query) {
+ searchGroup: debounce(function(query) {
this.loadingGroups = true
- axios.get(generateOcsUrl(`cloud/groups?offset=0&search=${encodeURIComponent(query)}&limit=20`, 2))
+ axios.get(generateOcsUrl('cloud/groups?offset=0&search={query}&limit=20', { query }))
.then(res => res.data.ocs)
.then(ocs => ocs.data.groups)
- .then(groups => { this.groups = _.sortedUniq(_.uniq(this.groups.concat(groups))) })
+ .then(groups => { this.groups = sortedUniq(uniq(this.groups.concat(groups))) })
.catch(err => console.error('could not search groups', err))
.then(() => { this.loadingGroups = false })
}, 500),
@@ -156,11 +171,14 @@ export default {
}
</script>
-<style>
+<style scoped>
.two-factor-loading {
display: inline-block;
vertical-align: sub;
- margin-left: -2px;
- margin-right: 1px;
+ margin-inline: -2px 1px;
+ }
+
+ .top-margin {
+ margin-top: 0.5rem;
}
</style>