Skip to content

Commit

Permalink
feat: added UserManagement view
Browse files Browse the repository at this point in the history
  • Loading branch information
Tbaile committed Oct 16, 2023
1 parent fa86319 commit 2b63b59
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 1 deletion.
11 changes: 11 additions & 0 deletions public/i18n/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
},
"standalone": {
"shell": {
"account": "Account",
"sign_out": "Sign out",
"open_sidebar": "Open sidebar",
"close_sidebar": "Close sidebar",
Expand Down Expand Up @@ -581,6 +582,16 @@
},
"report": {
"title": "Report"
},
"account_management": {
"title": "Account Management for '{name}'",
"change_password": "Change password",
"change_password_description": "Beware, if you change the password fo the 'root' user, you will change the password for shell access too."
},
"change_password": {
"new_password": "New password",
"confirm_password": "Confirm password",
"success_message": "Password changed successfully."
}
},
"controller": {
Expand Down
7 changes: 6 additions & 1 deletion src/components/standalone/StandaloneAppShell.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@ import { isStandaloneMode, getCompanyName } from '@/lib/config'
import { useI18n } from 'vue-i18n'
import UciChangesModal from './UciChangesModal.vue'
import { isEmpty } from 'lodash'
import router from '@/router'

const loginStore = useLoginStore()
const uciChangesStore = useUciPendingChangesStore()
const themeStore = useThemeStore()
const { t } = useI18n()

const accountMenu = [
// { name: 'Your profile', action: null }, ////
{
name: t('standalone.shell.account'),
action: () => router.push('/standalone/user'),
disabled: !isStandaloneMode()
},
{
name: t('standalone.shell.sign_out'),
action: loginStore.logout,
Expand Down
97 changes: 97 additions & 0 deletions src/components/standalone/account/ChangePassword.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<!--
Copyright (C) 2023 Nethesis S.r.l.
SPDX-License-Identifier: GPL-3.0-or-later
-->

<script lang="ts" setup>
import {
getAxiosErrorMessage,
NeButton,
NeInlineNotification,
NeTextInput
} from '@nethserver/vue-tailwind-lib'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { MessageBag, validateEqual, validatePassword, validateRequired } from '@/lib/validation'
import { useLoginStore } from '@/stores/standalone/standaloneLogin'
import { ubusCall } from '@/lib/standalone/ubus'
import type { AxiosError } from 'axios'

const { t } = useI18n()

const loginStore = useLoginStore()

const newPassword = ref('')
const confirmPassword = ref('')

const validationBag = ref(new MessageBag())

const loading = ref(false)
const error = ref<Error>()
const success = ref(false)

function validate(): boolean {
validationBag.value.clear()
let errMessage = validateRequired(newPassword.value).errMessage
if (errMessage) {
validationBag.value.set('new_password', String(errMessage))
}
errMessage = validatePassword(newPassword.value).errMessage
if (errMessage) {
validationBag.value.set('new_password', String(errMessage))
}
errMessage = validateEqual(newPassword.value, confirmPassword.value).errMessage
if (errMessage) {
validationBag.value.set('confirm_password', String(errMessage))
}
return validationBag.value.size == 0
}

function updatePassword() {
if (validate()) {
loading.value = true
success.value = false
ubusCall('ns.account', 'set-password', {
username: loginStore.username,
password: newPassword.value
})
.then(() => {
success.value = true
newPassword.value = ''
confirmPassword.value = ''
})
.catch((reason: AxiosError) => (error.value = reason))
.finally(() => (loading.value = false))
}
}
</script>

<template>
<div class="space-y-6">
<NeInlineNotification v-if="error" :title="t(getAxiosErrorMessage(error))" kind="error" />
<NeInlineNotification
v-if="success"
:title="t('standalone.change_password.success_message')"
kind="success"
/>
<NeTextInput
v-model="newPassword"
:disabled="loading"
:invalid-message="t(validationBag.getFirstFor('new_password'))"
:label="t('standalone.change_password.new_password')"
is-password
/>
<NeTextInput
v-model="confirmPassword"
:disabled="loading"
:invalid-message="t(validationBag.getFirstFor('confirm_password'))"
:label="t('standalone.change_password.confirm_password')"
is-password
/>
<div class="flex justify-end">
<NeButton :disabled="loading" :loading="loading" kind="primary" @click="updatePassword()">
{{ t('common.save') }}
</NeButton>
</div>
</div>
</template>
5 changes: 5 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ const standaloneRoutes = [
path: 'logs',
name: 'Logs',
component: () => import('../views/standalone/LogsView.vue')
},
{
path: 'user',
name: 'UserManagement',
component: () => import('../views/standalone/UserManagement.vue')
}
]

Expand Down
28 changes: 28 additions & 0 deletions src/views/standalone/UserManagement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!--
Copyright (C) 2023 Nethesis S.r.l.
SPDX-License-Identifier: GPL-3.0-or-later
-->

<script lang="ts" setup>
import { NeTitle } from '@nethserver/vue-tailwind-lib'
import { useI18n } from 'vue-i18n'
import ChangePassword from '@/components/standalone/account/ChangePassword.vue'
import { useLoginStore } from '@/stores/standalone/standaloneLogin'
import FormLayout from '@/components/standalone/FormLayout.vue'

const { t } = useI18n()

const loginStore = useLoginStore()
</script>

<template>
<NeTitle>{{ t('standalone.account_management.title', { name: loginStore.username }) }}</NeTitle>
<div class="max-w-3xl">
<FormLayout
:title="t('standalone.account_management.change_password')"
:description="t('standalone.account_management.change_password_description')"
>
<ChangePassword />
</FormLayout>
</div>
</template>

0 comments on commit 2b63b59

Please sign in to comment.