Files
authentication_provider_pas…/src/components/CredentialSetupPanel.vue
T
Sebastian 3e921fc07e
Integration Tests / Integration Tests (pull_request) Successful in 52s
feat: pemissions
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-07-23 18:01:26 -04:00

150 lines
3.7 KiB
Vue

<script setup lang="ts">
import { ref } from 'vue';
interface User {
uid: string;
identity: string;
label: string;
}
const props = defineProps<{
user: User;
}>();
const loading = ref(false);
const error = ref<string | null>(null);
const success = ref<string | null>(null);
const password = ref('');
const confirmPassword = ref('');
const expanded = ref(false);
const setPassword = async () => {
if (password.value !== confirmPassword.value) {
error.value = 'Passwords do not match';
return;
}
if (password.value.length < 8) {
error.value = 'Password must be at least 8 characters';
return;
}
loading.value = true;
error.value = null;
try {
const response = await fetch('/m/authentication_provider_password/reset', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify({
uid: props.user.uid,
password: password.value,
}),
});
if (response.ok) {
success.value = 'Password set successfully';
password.value = '';
confirmPassword.value = '';
expanded.value = false;
} else {
const data = await response.json();
error.value = data.error || 'Failed to set password';
}
} catch (err: any) {
error.value = err.message || 'Failed to set password';
} finally {
loading.value = false;
}
};
</script>
<template>
<VExpansionPanels v-model="expanded">
<VExpansionPanel>
<VExpansionPanelTitle>
<div class="d-flex align-center">
<VIcon icon="mdi-lock" class="mr-3" />
<div>
<div class="font-weight-medium">Password Authentication</div>
<div class="text-caption text-grey">
{{ success ? 'Password configured' : 'Set a password for this user' }}
</div>
</div>
<VSpacer />
<VChip
v-if="success"
color="success"
size="small"
prepend-icon="mdi-check"
>
Configured
</VChip>
</div>
</VExpansionPanelTitle>
<VExpansionPanelText>
<VAlert
v-if="error"
type="error"
closable
class="mb-4"
@click:close="error = null"
>
{{ error }}
</VAlert>
<VAlert
v-if="success"
type="success"
closable
class="mb-4"
@click:close="success = null"
>
{{ success }}
</VAlert>
<VForm @submit.prevent="setPassword">
<VTextField
v-model="password"
name="new-password"
label="Password"
type="password"
variant="outlined"
class="mb-4"
required
hint="Minimum 8 characters"
persistent-hint
autocomplete="suppress"
/>
<VTextField
v-model="confirmPassword"
name="confirm-password"
label="Confirm Password"
type="password"
variant="outlined"
required
autocomplete="suppress"
:error="confirmPassword.length > 0 && confirmPassword !== password"
:error-messages="confirmPassword.length > 0 && confirmPassword !== password ? ['Passwords do not match'] : []"
/>
<div class="mt-4">
<VBtn
type="submit"
color="primary"
:loading="loading"
:disabled="success !== null"
>
Set Password
</VBtn>
</div>
</VForm>
</VExpansionPanelText>
</VExpansionPanel>
</VExpansionPanels>
</template>