114 lines
3.6 KiB
Vue
114 lines
3.6 KiB
Vue
<template>
|
|
<div class="space-y-4">
|
|
<form @submit.prevent="changePassword" ref="passwordChangeForm">
|
|
<sl-input
|
|
label="Current password"
|
|
type="password"
|
|
autocomplete="current-password"
|
|
placeholder="Current Password"
|
|
required
|
|
help-text="Enter your current password"
|
|
:value="currentPassword"
|
|
@input="checkCurrent"
|
|
@sl-input="currentPassword = $event.target.value"
|
|
ref="currentPasswordField"
|
|
password-toggle
|
|
></sl-input>
|
|
<sl-input
|
|
label="New Password"
|
|
type="password"
|
|
required
|
|
placeholder="New Password"
|
|
autocomplete="new-password"
|
|
help-text="Enter your new password"
|
|
:value="newPassword"
|
|
@sl-input="newPassword = $event.target.value"
|
|
ref="newPasswordField"
|
|
password-toggle
|
|
></sl-input>
|
|
<sl-input
|
|
label="New Password (repeat)"
|
|
type="password"
|
|
required
|
|
placeholder="New Password"
|
|
autocomplete="new-password"
|
|
help-text="Confirm your new password by typing it again"
|
|
:value="newPasswordConfirm"
|
|
@sl-input="newPasswordConfirm = $event.target.value"
|
|
@blur="checkPasswords"
|
|
ref="newPasswordFieldConfirm"
|
|
password-toggle
|
|
></sl-input>
|
|
<sl-button class="mr-4" type="submit" variant="primary">Change Password</sl-button>
|
|
<sl-button variant="default" @click="cancelChangePassword">Cancel</sl-button>
|
|
</form>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
import { useAlertsStore } from '@/store/useAlertsStore'
|
|
import { SshecretAdmin } from '@/client'
|
|
import type { UserPasswordChange } from '@/client'
|
|
import { assertSdkResponseOk } from '@/api/assertSdkResponseOk'
|
|
import { ApiError, ValidationError } from '@/api/errors'
|
|
import { setFieldValidation } from '@/api/validation'
|
|
|
|
const currentPassword = ref<string>('')
|
|
const newPassword = ref<string>('')
|
|
const newPasswordConfirm = ref<string>('')
|
|
|
|
const passwordChangeForm = ref<HTMLFormElement>()
|
|
const currentPasswordField = ref<SlInput>()
|
|
const newPasswordField = ref<SlInput>()
|
|
const newPasswordFieldConfirm = ref<Slinput>()
|
|
|
|
const alerts = useAlertsStore()
|
|
|
|
const emit = defineEmits<{ (e: 'changed'): void; (e: 'cancel'): void }>()
|
|
|
|
function checkCurrent() {
|
|
setFieldValidation(currentPasswordField)
|
|
currentPasswordField.value.reportValidity()
|
|
}
|
|
|
|
function checkPasswords() {
|
|
if (newPassword.value !== newPasswordConfirm.value) {
|
|
setFieldValidation(newPasswordFieldConfirm, 'Passwords do not match match')
|
|
} else {
|
|
setFieldValidation(newPasswordFieldConfirm)
|
|
}
|
|
}
|
|
|
|
function resetForm() {
|
|
passwordChangeForm.value?.reset()
|
|
}
|
|
|
|
function cancelChangePassword() {
|
|
resetForm()
|
|
emit('cancel')
|
|
}
|
|
async function changePassword() {
|
|
const data: UserPasswordChange = {
|
|
current_password: currentPassword.value,
|
|
new_password: newPassword.value,
|
|
new_password_confirm: newPasswordConfirm.value,
|
|
}
|
|
const response = await SshecretAdmin.changePasswordApiV1PasswordPost({ body: data })
|
|
try {
|
|
assertSdkResponseOk(response)
|
|
emit('changed')
|
|
resetForm()
|
|
} catch (err) {
|
|
if (err instanceof ValidationError) {
|
|
// This should be caught in js, but we might as well
|
|
setFieldValidation(newPasswordFieldConfirm, 'Passwords do not match match')
|
|
} else if (err instanceof ApiError && err.message.includes('Invalid current password')) {
|
|
setFieldValidation(currentPasswordField, 'Invalid current password')
|
|
} else {
|
|
alerts.showAlert(err.message, 'error', 'Error changing password')
|
|
}
|
|
}
|
|
}
|
|
</script>
|