diff options
Diffstat (limited to 'apps/settings/src/components/AdminTwoFactor.vue')
-rw-r--r-- | apps/settings/src/components/AdminTwoFactor.vue | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/apps/settings/src/components/AdminTwoFactor.vue b/apps/settings/src/components/AdminTwoFactor.vue new file mode 100644 index 00000000000..a1f28f5cfdd --- /dev/null +++ b/apps/settings/src/components/AdminTwoFactor.vue @@ -0,0 +1,168 @@ +<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> + <p v-if="loading"> + <span class="icon-loading-small two-factor-loading"></span> + <span>{{ t('settings', 'Enforce two-factor authentication') }}</span> + </p> + <p v-else> + <input type="checkbox" + id="two-factor-enforced" + class="checkbox" + v-model="enforced"> + <label for="two-factor-enforced">{{ t('settings', 'Enforce two-factor authentication') }}</label> + </p> + <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> + {{ t('settings', 'Two-factor authentication is enforced for all members of the following groups.') }} + </p> + <p> + <Multiselect v-model="enforcedGroups" + :options="groups" + :placeholder="t('settings', 'Enforced groups')" + :disabled="loading" + :multiple="true" + :searchable="true" + @search-change="searchGroup" + :loading="loadingGroups" + :show-no-options="false" + :close-on-select="false"> + </Multiselect> + </p> + <p> + {{ t('settings', 'Two-factor authentication is not enforced for members of the following groups.') }} + </p> + <p> + <Multiselect v-model="excludedGroups" + :options="groups" + :placeholder="t('settings', 'Excluded groups')" + :disabled="loading" + :multiple="true" + :searchable="true" + @search-change="searchGroup" + :loading="loadingGroups" + :show-no-options="false" + :close-on-select="false"> + </Multiselect> + </p> + <p> + <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.') }} + </em> + </p> + </template> + <p> + <button class="button primary" + v-if="dirty" + v-on:click="saveChanges" + :disabled="loading"> + {{ t('settings', 'Save changes') }} + </button> + </p> + </div> +</template> + +<script> + import Axios from 'nextcloud-axios' + import { mapState } from 'vuex' + import {Multiselect} from 'nextcloud-vue' + import _ from 'lodash' + + export default { + name: "AdminTwoFactor", + components: { + Multiselect + }, + data () { + return { + loading: false, + dirty: false, + groups: [], + loadingGroups: false, + } + }, + computed: { + enforced: { + get: function () { + return this.$store.state.enforced + }, + set: function (val) { + this.dirty = true + this.$store.commit('setEnforced', val) + } + }, + enforcedGroups: { + get: function () { + return this.$store.state.enforcedGroups + }, + set: function (val) { + this.dirty = true + this.$store.commit('setEnforcedGroups', val) + } + }, + excludedGroups: { + get: function () { + return this.$store.state.excludedGroups + }, + set: function (val) { + this.dirty = true + this.$store.commit('setExcludedGroups', val) + } + }, + }, + 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))) + + // 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) { + this.loadingGroups = true + Axios.get(OC.linkToOCS(`cloud/groups?offset=0&search=${encodeURIComponent(query)}&limit=20`, 2)) + .then(res => res.data.ocs) + .then(ocs => ocs.data.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), + + saveChanges () { + this.loading = true + + const data = { + enforced: this.enforced, + enforcedGroups: this.enforcedGroups, + excludedGroups: this.excludedGroups, + } + Axios.put(OC.generateUrl('/settings/api/admin/twofactorauth'), data) + .then(resp => resp.data) + .then(state => { + this.state = state + this.dirty = false + }) + .catch(err => { + console.error('could not save changes', err) + }) + .then(() => this.loading = false) + } + } + } +</script> + +<style> + .two-factor-loading { + display: inline-block; + vertical-align: sub; + margin-left: -2px; + margin-right: 1px; + } +</style> |