aboutsummaryrefslogtreecommitdiffstats
path: root/apps/settings/src/store/users.js
diff options
context:
space:
mode:
Diffstat (limited to 'apps/settings/src/store/users.js')
-rw-r--r--apps/settings/src/store/users.js807
1 files changed, 807 insertions, 0 deletions
diff --git a/apps/settings/src/store/users.js b/apps/settings/src/store/users.js
new file mode 100644
index 00000000000..7e4b9c4aebb
--- /dev/null
+++ b/apps/settings/src/store/users.js
@@ -0,0 +1,807 @@
+/**
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { getBuilder } from '@nextcloud/browser-storage'
+import { getCapabilities } from '@nextcloud/capabilities'
+import { parseFileSize } from '@nextcloud/files'
+import { showError } from '@nextcloud/dialogs'
+import { generateOcsUrl, generateUrl } from '@nextcloud/router'
+import { loadState } from '@nextcloud/initial-state'
+import axios from '@nextcloud/axios'
+
+import { GroupSorting } from '../constants/GroupManagement.ts'
+import { naturalCollator } from '../utils/sorting.ts'
+import api from './api.js'
+import logger from '../logger.ts'
+
+const usersSettings = loadState('settings', 'usersSettings', {})
+
+const localStorage = getBuilder('settings').persist(true).build()
+
+const defaults = {
+ /**
+ * @type {import('../views/user-types').IGroup}
+ */
+ group: {
+ id: '',
+ name: '',
+ usercount: 0,
+ disabled: 0,
+ canAdd: true,
+ canRemove: true,
+ },
+}
+
+const state = {
+ users: [],
+ groups: [
+ ...(usersSettings.getSubAdminGroups ?? []),
+ ...(usersSettings.systemGroups ?? []),
+ ],
+ orderBy: usersSettings.sortGroups ?? GroupSorting.UserCount,
+ minPasswordLength: 0,
+ usersOffset: 0,
+ usersLimit: 25,
+ disabledUsersOffset: 0,
+ disabledUsersLimit: 25,
+ userCount: usersSettings.userCount ?? 0,
+ showConfig: {
+ showStoragePath: localStorage.getItem('account_settings__showStoragePath') === 'true',
+ showUserBackend: localStorage.getItem('account_settings__showUserBackend') === 'true',
+ showFirstLogin: localStorage.getItem('account_settings__showFirstLogin') === 'true',
+ showLastLogin: localStorage.getItem('account_settings__showLastLogin') === 'true',
+ showNewUserForm: localStorage.getItem('account_settings__showNewUserForm') === 'true',
+ showLanguages: localStorage.getItem('account_settings__showLanguages') === 'true',
+ },
+}
+
+const mutations = {
+ appendUsers(state, usersObj) {
+ const existingUsers = state.users.map(({ id }) => id)
+ const newUsers = Object.values(usersObj)
+ .filter(({ id }) => !existingUsers.includes(id))
+
+ const users = state.users.concat(newUsers)
+ state.usersOffset += state.usersLimit
+ state.users = users
+ },
+ updateDisabledUsers(state, _usersObj) {
+ state.disabledUsersOffset += state.disabledUsersLimit
+ },
+ setPasswordPolicyMinLength(state, length) {
+ state.minPasswordLength = length !== '' ? length : 0
+ },
+ /**
+ * @param {object} state store state
+ * @param {import('../views/user-types.js').IGroup} newGroup new group
+ */
+ addGroup(state, newGroup) {
+ try {
+ if (typeof state.groups.find((group) => group.id === newGroup.id) !== 'undefined') {
+ return
+ }
+ // extend group to default values
+ const group = Object.assign({}, defaults.group, newGroup)
+ state.groups.unshift(group)
+ } catch (e) {
+ console.error('Can\'t create group', e)
+ }
+ },
+ renameGroup(state, { gid, displayName }) {
+ const groupIndex = state.groups.findIndex(groupSearch => groupSearch.id === gid)
+ if (groupIndex >= 0) {
+ const updatedGroup = state.groups[groupIndex]
+ updatedGroup.name = displayName
+ state.groups.splice(groupIndex, 1, updatedGroup)
+ }
+ },
+ removeGroup(state, gid) {
+ const groupIndex = state.groups.findIndex(groupSearch => groupSearch.id === gid)
+ if (groupIndex >= 0) {
+ state.groups.splice(groupIndex, 1)
+ }
+ },
+ addUserGroup(state, { userid, gid }) {
+ const group = state.groups.find(groupSearch => groupSearch.id === gid)
+ const user = state.users.find(user => user.id === userid)
+ // increase count if user is enabled
+ if (group && user.enabled && state.userCount > 0) {
+ group.usercount++
+ }
+ const groups = user.groups
+ groups.push(gid)
+ },
+ removeUserGroup(state, { userid, gid }) {
+ const group = state.groups.find(groupSearch => groupSearch.id === gid)
+ const user = state.users.find(user => user.id === userid)
+ // lower count if user is enabled
+ if (group && user.enabled && state.userCount > 0) {
+ group.usercount--
+ }
+ const groups = user.groups
+ groups.splice(groups.indexOf(gid), 1)
+ },
+ addUserSubAdmin(state, { userid, gid }) {
+ const groups = state.users.find(user => user.id === userid).subadmin
+ groups.push(gid)
+ },
+ removeUserSubAdmin(state, { userid, gid }) {
+ const groups = state.users.find(user => user.id === userid).subadmin
+ groups.splice(groups.indexOf(gid), 1)
+ },
+ deleteUser(state, userid) {
+ const userIndex = state.users.findIndex(user => user.id === userid)
+ this.commit('updateUserCounts', { user: state.users[userIndex], actionType: 'remove' })
+ state.users.splice(userIndex, 1)
+ },
+ addUserData(state, response) {
+ const user = response.data.ocs.data
+ state.users.unshift(user)
+ this.commit('updateUserCounts', { user, actionType: 'create' })
+ },
+ enableDisableUser(state, { userid, enabled }) {
+ const user = state.users.find(user => user.id === userid)
+ user.enabled = enabled
+ this.commit('updateUserCounts', { user, actionType: enabled ? 'enable' : 'disable' })
+ },
+ // update active/disabled counts, groups counts
+ updateUserCounts(state, { user, actionType }) {
+ // 0 is a special value
+ if (state.userCount === 0) {
+ return
+ }
+
+ const recentGroup = state.groups.find(group => group.id === '__nc_internal_recent')
+ const disabledGroup = state.groups.find(group => group.id === 'disabled')
+ switch (actionType) {
+ case 'enable':
+ case 'disable':
+ disabledGroup.usercount += user.enabled ? -1 : 1 // update Disabled Users count
+ recentGroup.usercount += user.enabled ? 1 : -1
+ state.userCount += user.enabled ? 1 : -1 // update Active Users count
+ user.groups.forEach(userGroup => {
+ const group = state.groups.find(groupSearch => groupSearch.id === userGroup)
+ if (!group) {
+ return
+ }
+ group.disabled += user.enabled ? -1 : 1 // update group disabled count
+ })
+ break
+ case 'create':
+ recentGroup.usercount++
+ state.userCount++ // increment Active Users count
+
+ user.groups.forEach(userGroup => {
+ const group = state.groups.find(groupSearch => groupSearch.id === userGroup)
+ if (!group) {
+ return
+ }
+ group.usercount++ // increment group total count
+ })
+ break
+ case 'remove':
+ if (user.enabled) {
+ recentGroup.usercount--
+ state.userCount-- // decrement Active Users count
+ user.groups.forEach(userGroup => {
+ const group = state.groups.find(groupSearch => groupSearch.id === userGroup)
+ if (!group) {
+ console.warn('User group ' + userGroup + ' does not exist during user removal')
+ return
+ }
+ group.usercount-- // decrement group total count
+ })
+ } else {
+ disabledGroup.usercount-- // decrement Disabled Users count
+ user.groups.forEach(userGroup => {
+ const group = state.groups.find(groupSearch => groupSearch.id === userGroup)
+ if (!group) {
+ return
+ }
+ group.disabled-- // decrement group disabled count
+ })
+ }
+ break
+ default:
+ logger.error(`Unknown action type in updateUserCounts: '${actionType}'`)
+ // not throwing error to interrupt execution as this is not fatal
+ }
+ },
+ setUserData(state, { userid, key, value }) {
+ if (key === 'quota') {
+ const humanValue = parseFileSize(value, true)
+ state.users.find(user => user.id === userid)[key][key] = humanValue !== null ? humanValue : value
+ } else {
+ state.users.find(user => user.id === userid)[key] = value
+ }
+ },
+
+ /**
+ * Reset users list
+ *
+ * @param {object} state the store state
+ */
+ resetUsers(state) {
+ state.users = []
+ state.usersOffset = 0
+ state.disabledUsersOffset = 0
+ },
+
+ /**
+ * Reset group list
+ *
+ * @param {object} state the store state
+ */
+ resetGroups(state) {
+ state.groups = [
+ ...(usersSettings.getSubAdminGroups ?? []),
+ ...(usersSettings.systemGroups ?? []),
+ ]
+ },
+
+ setShowConfig(state, { key, value }) {
+ localStorage.setItem(`account_settings__${key}`, JSON.stringify(value))
+ state.showConfig[key] = value
+ },
+
+ setGroupSorting(state, sorting) {
+ const oldValue = state.orderBy
+ state.orderBy = sorting
+
+ // Persist the value on the server
+ axios.post(
+ generateUrl('/settings/users/preferences/group.sortBy'),
+ {
+ value: String(sorting),
+ },
+ ).catch((error) => {
+ state.orderBy = oldValue
+ showError(t('settings', 'Could not set group sorting'))
+ logger.error(error)
+ })
+ },
+}
+
+const getters = {
+ getUsers(state) {
+ return state.users
+ },
+ getGroups(state) {
+ return state.groups
+ },
+ getSubAdminGroups() {
+ return usersSettings.subAdminGroups ?? []
+ },
+
+ getSortedGroups(state) {
+ const groups = [...state.groups]
+ if (state.orderBy === GroupSorting.UserCount) {
+ return groups.sort((a, b) => {
+ const numA = a.usercount - a.disabled
+ const numB = b.usercount - b.disabled
+ return (numA < numB) ? 1 : (numB < numA ? -1 : naturalCollator.compare(a.name, b.name))
+ })
+ } else {
+ return groups.sort((a, b) => naturalCollator.compare(a.name, b.name))
+ }
+ },
+ getGroupSorting(state) {
+ return state.orderBy
+ },
+ getPasswordPolicyMinLength(state) {
+ return state.minPasswordLength
+ },
+ getUsersOffset(state) {
+ return state.usersOffset
+ },
+ getUsersLimit(state) {
+ return state.usersLimit
+ },
+ getDisabledUsersOffset(state) {
+ return state.disabledUsersOffset
+ },
+ getDisabledUsersLimit(state) {
+ return state.disabledUsersLimit
+ },
+ getUserCount(state) {
+ return state.userCount
+ },
+ getShowConfig(state) {
+ return state.showConfig
+ },
+}
+
+const CancelToken = axios.CancelToken
+let searchRequestCancelSource = null
+
+const actions = {
+
+ /**
+ * search users
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {number} options.offset List offset to request
+ * @param {number} options.limit List number to return from offset
+ * @param {string} options.search Search amongst users
+ * @return {Promise}
+ */
+ searchUsers(context, { offset, limit, search }) {
+ search = typeof search === 'string' ? search : ''
+
+ return api.get(generateOcsUrl('cloud/users/details?offset={offset}&limit={limit}&search={search}', { offset, limit, search })).catch((error) => {
+ if (!axios.isCancel(error)) {
+ context.commit('API_FAILURE', error)
+ }
+ })
+ },
+
+ /**
+ * Get user details
+ *
+ * @param {object} context store context
+ * @param {string} userId user id
+ * @return {Promise}
+ */
+ getUser(context, userId) {
+ return api.get(generateOcsUrl(`cloud/users/${userId}`)).catch((error) => {
+ if (!axios.isCancel(error)) {
+ context.commit('API_FAILURE', error)
+ }
+ })
+ },
+
+ /**
+ * Get all users with full details
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {number} options.offset List offset to request
+ * @param {number} options.limit List number to return from offset
+ * @param {string} options.search Search amongst users
+ * @param {string} options.group Get users from group
+ * @return {Promise}
+ */
+ getUsers(context, { offset, limit, search, group }) {
+ if (searchRequestCancelSource) {
+ searchRequestCancelSource.cancel('Operation canceled by another search request.')
+ }
+ searchRequestCancelSource = CancelToken.source()
+ search = typeof search === 'string' ? search : ''
+
+ /**
+ * Adding filters in the search bar such as in:files, in:users, etc.
+ * collides with this particular search, so we need to remove them
+ * here and leave only the original search query
+ */
+ search = search.replace(/in:[^\s]+/g, '').trim()
+
+ group = typeof group === 'string' ? group : ''
+ if (group !== '') {
+ return api.get(generateOcsUrl('cloud/groups/{group}/users/details?offset={offset}&limit={limit}&search={search}', { group: encodeURIComponent(group), offset, limit, search }), {
+ cancelToken: searchRequestCancelSource.token,
+ })
+ .then((response) => {
+ const usersCount = Object.keys(response.data.ocs.data.users).length
+ if (usersCount > 0) {
+ context.commit('appendUsers', response.data.ocs.data.users)
+ }
+ return usersCount
+ })
+ .catch((error) => {
+ if (!axios.isCancel(error)) {
+ context.commit('API_FAILURE', error)
+ }
+ })
+ }
+
+ return api.get(generateOcsUrl('cloud/users/details?offset={offset}&limit={limit}&search={search}', { offset, limit, search }), {
+ cancelToken: searchRequestCancelSource.token,
+ })
+ .then((response) => {
+ const usersCount = Object.keys(response.data.ocs.data.users).length
+ if (usersCount > 0) {
+ context.commit('appendUsers', response.data.ocs.data.users)
+ }
+ return usersCount
+ })
+ .catch((error) => {
+ if (!axios.isCancel(error)) {
+ context.commit('API_FAILURE', error)
+ }
+ })
+ },
+
+ /**
+ * Get recent users with full details
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {number} options.offset List offset to request
+ * @param {number} options.limit List number to return from offset
+ * @param {string} options.search Search query
+ * @return {Promise<number>}
+ */
+ async getRecentUsers(context, { offset, limit, search }) {
+ const url = generateOcsUrl('cloud/users/recent?offset={offset}&limit={limit}&search={search}', { offset, limit, search })
+ try {
+ const response = await api.get(url)
+ const usersCount = Object.keys(response.data.ocs.data.users).length
+ if (usersCount > 0) {
+ context.commit('appendUsers', response.data.ocs.data.users)
+ }
+ return usersCount
+ } catch (error) {
+ context.commit('API_FAILURE', error)
+ }
+ },
+
+ /**
+ * Get disabled users with full details
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {number} options.offset List offset to request
+ * @param {number} options.limit List number to return from offset
+ * @param options.search
+ * @return {Promise<number>}
+ */
+ async getDisabledUsers(context, { offset, limit, search }) {
+ const url = generateOcsUrl('cloud/users/disabled?offset={offset}&limit={limit}&search={search}', { offset, limit, search })
+ try {
+ const response = await api.get(url)
+ const usersCount = Object.keys(response.data.ocs.data.users).length
+ if (usersCount > 0) {
+ context.commit('appendUsers', response.data.ocs.data.users)
+ context.commit('updateDisabledUsers', response.data.ocs.data.users)
+ }
+ return usersCount
+ } catch (error) {
+ context.commit('API_FAILURE', error)
+ }
+ },
+
+ getGroups(context, { offset, limit, search }) {
+ search = typeof search === 'string' ? search : ''
+ const limitParam = limit === -1 ? '' : `&limit=${limit}`
+ return api.get(generateOcsUrl('cloud/groups?offset={offset}&search={search}', { offset, search }) + limitParam)
+ .then((response) => {
+ if (Object.keys(response.data.ocs.data.groups).length > 0) {
+ response.data.ocs.data.groups.forEach(function(group) {
+ context.commit('addGroup', { id: group, name: group })
+ })
+ return true
+ }
+ return false
+ })
+ .catch((error) => context.commit('API_FAILURE', error))
+ },
+
+ /**
+ * Get all users with full details
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {number} options.offset List offset to request
+ * @param {number} options.limit List number to return from offset
+ * @param {string} options.search -
+ * @return {Promise}
+ */
+ getUsersFromList(context, { offset, limit, search }) {
+ search = typeof search === 'string' ? search : ''
+ return api.get(generateOcsUrl('cloud/users/details?offset={offset}&limit={limit}&search={search}', { offset, limit, search }))
+ .then((response) => {
+ if (Object.keys(response.data.ocs.data.users).length > 0) {
+ context.commit('appendUsers', response.data.ocs.data.users)
+ return true
+ }
+ return false
+ })
+ .catch((error) => context.commit('API_FAILURE', error))
+ },
+
+ /**
+ * Get all users with full details from a groupid
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {number} options.offset List offset to request
+ * @param {number} options.limit List number to return from offset
+ * @param {string} options.groupid -
+ * @return {Promise}
+ */
+ getUsersFromGroup(context, { groupid, offset, limit }) {
+ return api.get(generateOcsUrl('cloud/users/{groupId}/details?offset={offset}&limit={limit}', { groupId: encodeURIComponent(groupid), offset, limit }))
+ .then((response) => context.commit('getUsersFromList', response.data.ocs.data.users))
+ .catch((error) => context.commit('API_FAILURE', error))
+ },
+
+ getPasswordPolicyMinLength(context) {
+ if (getCapabilities().password_policy && getCapabilities().password_policy.minLength) {
+ context.commit('setPasswordPolicyMinLength', getCapabilities().password_policy.minLength)
+ return getCapabilities().password_policy.minLength
+ }
+ return false
+ },
+
+ /**
+ * Add group
+ *
+ * @param {object} context store context
+ * @param {string} gid Group id
+ * @return {Promise}
+ */
+ addGroup(context, gid) {
+ return api.requireAdmin().then((response) => {
+ return api.post(generateOcsUrl('cloud/groups'), { groupid: gid })
+ .then((response) => {
+ context.commit('addGroup', { id: gid, name: gid })
+ return { gid, displayName: gid }
+ })
+ .catch((error) => { throw error })
+ }).catch((error) => {
+ context.commit('API_FAILURE', { gid, error })
+ // let's throw one more time to prevent the view
+ // from adding the user to a group that doesn't exists
+ throw error
+ })
+ },
+
+ /**
+ * Rename group
+ *
+ * @param {object} context store context
+ * @param {string} groupid Group id
+ * @param {string} displayName Group display name
+ * @return {Promise}
+ */
+ renameGroup(context, { groupid, displayName }) {
+ return api.requireAdmin().then((response) => {
+ return api.put(generateOcsUrl('cloud/groups/{groupId}', { groupId: encodeURIComponent(groupid) }), { key: 'displayname', value: displayName })
+ .then((response) => {
+ context.commit('renameGroup', { gid: groupid, displayName })
+ return { groupid, displayName }
+ })
+ .catch((error) => { throw error })
+ }).catch((error) => {
+ context.commit('API_FAILURE', { groupid, error })
+ // let's throw one more time to prevent the view
+ // from renaming the group
+ throw error
+ })
+ },
+
+ /**
+ * Remove group
+ *
+ * @param {object} context store context
+ * @param {string} gid Group id
+ * @return {Promise}
+ */
+ removeGroup(context, gid) {
+ return api.requireAdmin().then((response) => {
+ return api.delete(generateOcsUrl('cloud/groups/{groupId}', { groupId: encodeURIComponent(gid) }))
+ .then((response) => context.commit('removeGroup', gid))
+ .catch((error) => { throw error })
+ }).catch((error) => context.commit('API_FAILURE', { gid, error }))
+ },
+
+ /**
+ * Add user to group
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {string} options.userid User id
+ * @param {string} options.gid Group id
+ * @return {Promise}
+ */
+ addUserGroup(context, { userid, gid }) {
+ return api.requireAdmin().then((response) => {
+ return api.post(generateOcsUrl('cloud/users/{userid}/groups', { userid }), { groupid: gid })
+ .then((response) => context.commit('addUserGroup', { userid, gid }))
+ .catch((error) => { throw error })
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }))
+ },
+
+ /**
+ * Remove user from group
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {string} options.userid User id
+ * @param {string} options.gid Group id
+ * @return {Promise}
+ */
+ removeUserGroup(context, { userid, gid }) {
+ return api.requireAdmin().then((response) => {
+ return api.delete(generateOcsUrl('cloud/users/{userid}/groups', { userid }), { groupid: gid })
+ .then((response) => context.commit('removeUserGroup', { userid, gid }))
+ .catch((error) => { throw error })
+ }).catch((error) => {
+ context.commit('API_FAILURE', { userid, error })
+ // let's throw one more time to prevent
+ // the view from removing the user row on failure
+ throw error
+ })
+ },
+
+ /**
+ * Add user to group admin
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {string} options.userid User id
+ * @param {string} options.gid Group id
+ * @return {Promise}
+ */
+ addUserSubAdmin(context, { userid, gid }) {
+ return api.requireAdmin().then((response) => {
+ return api.post(generateOcsUrl('cloud/users/{userid}/subadmins', { userid }), { groupid: gid })
+ .then((response) => context.commit('addUserSubAdmin', { userid, gid }))
+ .catch((error) => { throw error })
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }))
+ },
+
+ /**
+ * Remove user from group admin
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {string} options.userid User id
+ * @param {string} options.gid Group id
+ * @return {Promise}
+ */
+ removeUserSubAdmin(context, { userid, gid }) {
+ return api.requireAdmin().then((response) => {
+ return api.delete(generateOcsUrl('cloud/users/{userid}/subadmins', { userid }), { groupid: gid })
+ .then((response) => context.commit('removeUserSubAdmin', { userid, gid }))
+ .catch((error) => { throw error })
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }))
+ },
+
+ /**
+ * Mark all user devices for remote wipe
+ *
+ * @param {object} context store context
+ * @param {string} userid User id
+ * @return {Promise}
+ */
+ async wipeUserDevices(context, userid) {
+ try {
+ await api.requireAdmin()
+ return await api.post(generateOcsUrl('cloud/users/{userid}/wipe', { userid }))
+ } catch (error) {
+ context.commit('API_FAILURE', { userid, error })
+ return Promise.reject(new Error('Failed to wipe user devices'))
+ }
+ },
+
+ /**
+ * Delete a user
+ *
+ * @param {object} context store context
+ * @param {string} userid User id
+ * @return {Promise}
+ */
+ deleteUser(context, userid) {
+ return api.requireAdmin().then((response) => {
+ return api.delete(generateOcsUrl('cloud/users/{userid}', { userid }))
+ .then((response) => context.commit('deleteUser', userid))
+ .catch((error) => { throw error })
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }))
+ },
+
+ /**
+ * Add a user
+ *
+ * @param {object} context store context
+ * @param {Function} context.commit -
+ * @param {Function} context.dispatch -
+ * @param {object} options destructuring object
+ * @param {string} options.userid User id
+ * @param {string} options.password User password
+ * @param {string} options.displayName User display name
+ * @param {string} options.email User email
+ * @param {string} options.groups User groups
+ * @param {string} options.subadmin User subadmin groups
+ * @param {string} options.quota User email
+ * @param {string} options.language User language
+ * @param {string} options.manager User manager
+ * @return {Promise}
+ */
+ addUser({ commit, dispatch }, { userid, password, displayName, email, groups, subadmin, quota, language, manager }) {
+ return api.requireAdmin().then((response) => {
+ return api.post(generateOcsUrl('cloud/users'), { userid, password, displayName, email, groups, subadmin, quota, language, manager })
+ .then((response) => dispatch('addUserData', userid || response.data.ocs.data.id))
+ .catch((error) => { throw error })
+ }).catch((error) => {
+ commit('API_FAILURE', { userid, error })
+ throw error
+ })
+ },
+
+ /**
+ * Get user data and commit addition
+ *
+ * @param {object} context store context
+ * @param {string} userid User id
+ * @return {Promise}
+ */
+ addUserData(context, userid) {
+ return api.requireAdmin().then((response) => {
+ return api.get(generateOcsUrl('cloud/users/{userid}', { userid }))
+ .then((response) => context.commit('addUserData', response))
+ .catch((error) => { throw error })
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }))
+ },
+
+ /**
+ * Enable or disable user
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {string} options.userid User id
+ * @param {boolean} options.enabled User enablement status
+ * @return {Promise}
+ */
+ enableDisableUser(context, { userid, enabled = true }) {
+ const userStatus = enabled ? 'enable' : 'disable'
+ return api.requireAdmin().then((response) => {
+ return api.put(generateOcsUrl('cloud/users/{userid}/{userStatus}', { userid, userStatus }))
+ .then((response) => context.commit('enableDisableUser', { userid, enabled }))
+ .catch((error) => { throw error })
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }))
+ },
+
+ /**
+ * Edit user data
+ *
+ * @param {object} context store context
+ * @param {object} options destructuring object
+ * @param {string} options.userid User id
+ * @param {string} options.key User field to edit
+ * @param {string} options.value Value of the change
+ * @return {Promise}
+ */
+ async setUserData(context, { userid, key, value }) {
+ const allowedEmpty = ['email', 'displayname', 'manager']
+ const validKeys = ['email', 'language', 'quota', 'displayname', 'password', 'manager']
+
+ if (!validKeys.includes(key)) {
+ throw new Error('Invalid request data')
+ }
+
+ // If value is empty and the key doesn't allow empty values, throw error
+ if (value === '' && !allowedEmpty.includes(key)) {
+ throw new Error('Value cannot be empty for this field')
+ }
+
+ try {
+ await api.requireAdmin()
+ await api.put(generateOcsUrl('cloud/users/{userid}', { userid }), { key, value })
+ return context.commit('setUserData', { userid, key, value })
+ } catch (error) {
+ context.commit('API_FAILURE', { userid, error })
+ throw error
+ }
+ },
+
+ /**
+ * Send welcome mail
+ *
+ * @param {object} context store context
+ * @param {string} userid User id
+ * @return {Promise}
+ */
+ sendWelcomeMail(context, userid) {
+ return api.requireAdmin().then((response) => {
+ return api.post(generateOcsUrl('cloud/users/{userid}/welcome', { userid }))
+ .then(response => true)
+ .catch((error) => { throw error })
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }))
+ },
+}
+
+export default { state, mutations, getters, actions }