diff options
Diffstat (limited to 'apps/settings/src')
-rw-r--r-- | apps/settings/src/components/AppNavigationGroupList.vue | 18 | ||||
-rw-r--r-- | apps/settings/src/components/PersonalInfo/FediverseSection.vue | 9 | ||||
-rw-r--r-- | apps/settings/src/components/PersonalInfo/TwitterSection.vue | 4 | ||||
-rw-r--r-- | apps/settings/src/components/UserList.vue | 6 | ||||
-rw-r--r-- | apps/settings/src/components/Users/NewUserDialog.vue | 17 | ||||
-rw-r--r-- | apps/settings/src/store/apps.js | 3 | ||||
-rw-r--r-- | apps/settings/src/store/users.js | 19 |
7 files changed, 56 insertions, 20 deletions
diff --git a/apps/settings/src/components/AppNavigationGroupList.vue b/apps/settings/src/components/AppNavigationGroupList.vue index b32a07bc9b8..5c648a17098 100644 --- a/apps/settings/src/components/AppNavigationGroupList.vue +++ b/apps/settings/src/components/AppNavigationGroupList.vue @@ -57,12 +57,16 @@ </template> <script setup lang="ts"> +import type CancelablePromise from 'cancelable-promise' +import type { IGroup } from '../views/user-types.d.ts' + +import { mdiAccountGroup, mdiPlus } from '@mdi/js' +import { showError } from '@nextcloud/dialogs' +import { t } from '@nextcloud/l10n' +import { useElementVisibility } from '@vueuse/core' import { computed, ref, watch, onBeforeMount } from 'vue' import { Fragment } from 'vue-frag' import { useRoute, useRouter } from 'vue-router/composables' -import { useElementVisibility } from '@vueuse/core' -import { showError } from '@nextcloud/dialogs' -import { mdiAccountGroup, mdiPlus } from '@mdi/js' import NcActionInput from '@nextcloud/vue/components/NcActionInput' import NcActionText from '@nextcloud/vue/components/NcActionText' @@ -137,12 +141,16 @@ watch(groupsSearchQuery, async () => { }) /** Cancelable promise for search groups request */ -const promise = ref(null) +const promise = ref<CancelablePromise<IGroup[]>>() /** * Load groups */ async function loadGroups() { + if (!isAdminOrDelegatedAdmin.value) { + return + } + if (promise.value) { promise.value.cancel() } @@ -163,7 +171,7 @@ async function loadGroups() { } catch (error) { logger.error(t('settings', 'Failed to load groups'), { error }) } - promise.value = null + promise.value = undefined loadingGroups.value = false } diff --git a/apps/settings/src/components/PersonalInfo/FediverseSection.vue b/apps/settings/src/components/PersonalInfo/FediverseSection.vue index 65400ce0e45..043fa6e64b9 100644 --- a/apps/settings/src/components/PersonalInfo/FediverseSection.vue +++ b/apps/settings/src/components/PersonalInfo/FediverseSection.vue @@ -19,7 +19,7 @@ import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js' import AccountPropertySection from './shared/AccountPropertySection.vue' -const { fediverse } = loadState<AccountProperties>('settings', 'personalInfoParameters', {}) +const { fediverse } = loadState<AccountProperties>('settings', 'personalInfoParameters') const value = ref({ ...fediverse }) const readable = NAME_READABLE_ENUM[fediverse.name] @@ -29,11 +29,18 @@ const readable = NAME_READABLE_ENUM[fediverse.name] * @param text The potential fediverse handle */ function onValidate(text: string): boolean { + // allow to clear the value + if (text === '') { + return true + } + + // check its in valid format const result = text.match(/^@?([^@/]+)@([^@/]+)$/) if (result === null) { return false } + // check its a valid URL try { return URL.parse(`https://${result[2]}/`) !== null } catch { diff --git a/apps/settings/src/components/PersonalInfo/TwitterSection.vue b/apps/settings/src/components/PersonalInfo/TwitterSection.vue index 802f96087c2..43d08f81e3f 100644 --- a/apps/settings/src/components/PersonalInfo/TwitterSection.vue +++ b/apps/settings/src/components/PersonalInfo/TwitterSection.vue @@ -19,7 +19,7 @@ import { ref } from 'vue' import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.ts' import AccountPropertySection from './shared/AccountPropertySection.vue' -const { twitter } = loadState<AccountProperties>('settings', 'personalInfoParameters', {}) +const { twitter } = loadState<AccountProperties>('settings', 'personalInfoParameters') const value = ref({ ...twitter }) const readable = NAME_READABLE_ENUM[twitter.name] @@ -29,6 +29,6 @@ const readable = NAME_READABLE_ENUM[twitter.name] * @param text The potential twitter handle */ function onValidate(text: string): boolean { - return text.match(/^@?([a-zA-Z0-9_]{2,15})$/) !== null + return text === '' || text.match(/^@?([a-zA-Z0-9_]{2,15})$/) !== null } </script> diff --git a/apps/settings/src/components/UserList.vue b/apps/settings/src/components/UserList.vue index 5d6bd5f04ee..84c204805cc 100644 --- a/apps/settings/src/components/UserList.vue +++ b/apps/settings/src/components/UserList.vue @@ -350,11 +350,13 @@ export default { setNewUserDefaultGroup(value) { // Is no value set, but user is a line manager we set their group as this is a requirement for line manager if (!value && !this.settings.isAdmin && !this.settings.isDelegatedAdmin) { + const groups = this.$store.getters.getSubAdminGroups // if there are multiple groups we do not know which to add, // so we cannot make the managers life easier by preselecting it. - if (this.groups.length === 1) { - value = this.groups[0].id + if (groups.length === 1) { + this.newUser.groups = [...groups] } + return } if (value) { diff --git a/apps/settings/src/components/Users/NewUserDialog.vue b/apps/settings/src/components/Users/NewUserDialog.vue index 3e50efc2072..19445bc187e 100644 --- a/apps/settings/src/components/Users/NewUserDialog.vue +++ b/apps/settings/src/components/Users/NewUserDialog.vue @@ -61,6 +61,7 @@ :required="newUser.password === '' || settings.newUserRequireEmail" /> <div class="dialog__item"> <NcSelect class="dialog__select" + data-test="groups" :input-label="!settings.isAdmin && !settings.isDelegatedAdmin ? t('settings', 'Member of the following groups (required)') : t('settings', 'Member of the following groups')" :placeholder="t('settings', 'Set account groups')" :disabled="loading.groups || loading.all" @@ -69,7 +70,7 @@ label="name" :close-on-select="false" :multiple="true" - :taggable="true" + :taggable="settings.isAdmin || settings.isDelegatedAdmin" :required="!settings.isAdmin && !settings.isDelegatedAdmin" :create-option="(value) => ({ id: value, name: value, isCreating: true })" @search="searchGroups" @@ -178,7 +179,7 @@ export default { data() { return { - availableGroups: this.$store.getters.getSortedGroups.filter(group => group.id !== '__nc_internal_recent' && group.id !== 'disabled'), + availableGroups: [], possibleManagers: [], // TRANSLATORS This string describes a manager in the context of an organization managerInputLabel: t('settings', 'Manager'), @@ -235,6 +236,13 @@ export default { }, mounted() { + // admins also can assign the system groups + if (this.isAdmin || this.isDelegatedAdmin) { + this.availableGroups = this.$store.getters.getSortedGroups.filter(group => group.id !== '__nc_internal_recent' && group.id !== 'disabled') + } else { + this.availableGroups = [...this.$store.getters.getSubAdminGroups] + } + this.$refs.username?.focus?.() }, @@ -273,6 +281,11 @@ export default { }, async searchGroups(query, toggleLoading) { + if (!this.isAdmin && !this.isDelegatedAdmin) { + // managers cannot search for groups + return + } + if (this.promise) { this.promise.cancel() } diff --git a/apps/settings/src/store/apps.js b/apps/settings/src/store/apps.js index c58651a3cf5..e0068d3892e 100644 --- a/apps/settings/src/store/apps.js +++ b/apps/settings/src/store/apps.js @@ -5,6 +5,7 @@ import api from './api.js' import Vue from 'vue' +import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' import { showError, showInfo } from '@nextcloud/dialogs' import { loadState } from '@nextcloud/initial-state' @@ -191,7 +192,7 @@ const actions = { }) // check for server health - return api.get(generateUrl('apps/files/')) + return axios.get(generateUrl('apps/files/')) .then(() => { if (response.data.update_required) { showInfo( diff --git a/apps/settings/src/store/users.js b/apps/settings/src/store/users.js index a6298a38e2d..3734b7008df 100644 --- a/apps/settings/src/store/users.js +++ b/apps/settings/src/store/users.js @@ -36,7 +36,10 @@ const defaults = { const state = { users: [], - groups: [...(usersSettings.systemGroups ?? [])], + groups: [ + ...(usersSettings.getSubAdminGroups ?? []), + ...(usersSettings.systemGroups ?? []), + ], orderBy: usersSettings.sortGroups ?? GroupSorting.UserCount, minPasswordLength: 0, usersOffset: 0, @@ -232,12 +235,10 @@ const mutations = { * @param {object} state the store state */ resetGroups(state) { - const systemGroups = state.groups.filter(group => [ - 'admin', - '__nc_internal_recent', - 'disabled', - ].includes(group.id)) - state.groups = [...systemGroups] + state.groups = [ + ...(usersSettings.getSubAdminGroups ?? []), + ...(usersSettings.systemGroups ?? []), + ] }, setShowConfig(state, { key, value }) { @@ -270,6 +271,10 @@ const getters = { getGroups(state) { return state.groups }, + getSubAdminGroups() { + return usersSettings.subAdminGroups ?? [] + }, + getSortedGroups(state) { const groups = [...state.groups] if (state.orderBy === GroupSorting.UserCount) { |