diff --git a/dashboard/src/components/GroupDialog.vue b/dashboard/src/components/GroupDialog.vue index 864db22e1..907e30c3d 100644 --- a/dashboard/src/components/GroupDialog.vue +++ b/dashboard/src/components/GroupDialog.vue @@ -26,6 +26,7 @@ const allApps = ref([]); async function onSubmit() { busy.value = true; + formError.value = ''; if (group.value) { const [error] = await groupsModel.update(group.value.id, name.value, users.value.map(u => u.id), apps.value.map(u => u.id)); @@ -82,12 +83,12 @@ defineExpose({ @confirm="onSubmit()" >

{{ $t('users.editGroupDialog.externalLdapWarning') }}

-
+
- + diff --git a/dashboard/src/components/UserDialog.vue b/dashboard/src/components/UserDialog.vue new file mode 100644 index 000000000..05d987b5d --- /dev/null +++ b/dashboard/src/components/UserDialog.vue @@ -0,0 +1,220 @@ + + + diff --git a/dashboard/src/models/UsersModel.js b/dashboard/src/models/UsersModel.js index 77e08fce1..7b53a04b4 100644 --- a/dashboard/src/models/UsersModel.js +++ b/dashboard/src/models/UsersModel.js @@ -31,6 +31,40 @@ function create() { return [null, users]; }, + async add(user) { + const data = { + email: user.email, + fallbackEmail: user.fallbackEmail, + displayName: user.displayName, + role: user.role + }; + + if (user.username) data.username = user.username; + if (user.password) data.password = user.password; + + let result; + try { + result = await fetcher.post(`${origin}/api/v1/users`, data, { access_token: accessToken }); + } catch (e) { + return [e]; + } + + if (result.status !== 201) return [result]; + + return [null, result.body]; + }, + async update(id, data) { + let result; + try { + result = await fetcher.post(`${origin}/api/v1/users/${id}/profile`, data, { access_token: accessToken }); + } catch (e) { + return [e]; + } + + if (result.status !== 204) return [result]; + + return [null]; + }, async remove(id) { let result; try { @@ -42,6 +76,39 @@ function create() { if (result.status !== 204) return [result]; return [null]; }, + async setLocalGroups(id, groupIds) { + let result; + try { + result = await fetcher.put(`${origin}/api/v1/users/${id}/groups`, { groupIds }, { access_token: accessToken }); + } catch (e) { + return [e]; + } + + if (result.status !== 204) return [result]; + return [null]; + }, + async setRole(id, role) { + let result; + try { + result = await fetcher.put(`${origin}/api/v1/users/${id}/role`, { role }, { access_token: accessToken }); + } catch (e) { + return [e]; + } + + if (result.status !== 204) return [result]; + return [null]; + }, + async setActive(id, active) { + let result; + try { + result = await fetcher.put(`${origin}/api/v1/users/${id}/active`, { active }, { access_token: accessToken }); + } catch (e) { + return [e]; + } + + if (result.status !== 204) return [result]; + return [null]; + }, async setGhost(id, password, expiresAt = 0) { const data = { password }; @@ -76,6 +143,17 @@ function create() { return [e]; } + if (result.status !== 202) return [result]; + return [null]; + }, + async sendInviteEmail(id, email) { + let result; + try { + result = await fetcher.post(`${origin}/api/v1/users/${id}/send_invite_email`, { email }, { access_token: accessToken }); + } catch (e) { + return [e]; + } + if (result.status !== 202) return [result]; return [null]; }, diff --git a/dashboard/src/views/UsersView.vue b/dashboard/src/views/UsersView.vue index 06cfdca9e..1d5ee77d0 100644 --- a/dashboard/src/views/UsersView.vue +++ b/dashboard/src/views/UsersView.vue @@ -8,6 +8,7 @@ import { ref, onMounted, computed, useTemplateRef } from 'vue'; import { Button, ButtonGroup, TextInput, Dropdown, TableView, InputDialog } from 'pankow'; import { ROLES } from '../constants.js'; import Section from '../components/Section.vue'; +import UserDialog from '../components/UserDialog.vue'; import GroupDialog from '../components/GroupDialog.vue'; import ImpersonateDialog from '../components/ImpersonateDialog.vue'; import PasswordResetDialog from '../components/PasswordResetDialog.vue'; @@ -49,6 +50,7 @@ const groupsById = ref({}); const roles = ref([]); const inputDialog = useTemplateRef('inputDialog'); +const userDialog = useTemplateRef('userDialog'); const groupDialog = useTemplateRef('groupDialog'); const impersonateDialog = useTemplateRef('impersonateDialog'); const passwordResetDialog = useTemplateRef('passwordResetDialog'); @@ -125,6 +127,10 @@ function onPasswordReset(user) { passwordResetDialog.value.open(user); } +function onEditOrAddUser(user = null) { + userDialog.value.open(user); +} + function onEditOrAddGroup(group = null) { groupDialog.value.open(group); } @@ -188,6 +194,7 @@ onMounted(async () => {