portal: tighten onboarding confirmation flow
This commit is contained in:
parent
87c3cb35ab
commit
8677efaa94
@ -187,75 +187,6 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div v-if="step.action === 'auto' || step.action === 'confirm'" class="step-actions">
|
||||
<button
|
||||
class="secondary"
|
||||
type="button"
|
||||
@click="confirmStep(step)"
|
||||
:disabled="loading || isStepDone(step.id) || isStepBlocked(step.id)"
|
||||
>
|
||||
Confirm
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="step.action === 'keycloak_rotate'" class="step-actions">
|
||||
<button
|
||||
class="secondary"
|
||||
type="button"
|
||||
@click="requestKeycloakPasswordRotation"
|
||||
:disabled="
|
||||
!auth.authenticated ||
|
||||
loading ||
|
||||
isStepDone('keycloak_password_rotated') ||
|
||||
isStepBlocked('keycloak_password_rotated') ||
|
||||
keycloakPasswordRotationRequested
|
||||
"
|
||||
>
|
||||
Start Keycloak update
|
||||
</button>
|
||||
<a class="mono" href="https://live.bstein.dev" target="_blank" rel="noreferrer">Open Element</a>
|
||||
<button
|
||||
class="secondary"
|
||||
type="button"
|
||||
@click="confirmStep(step)"
|
||||
:disabled="loading || isStepDone(step.id) || isStepBlocked(step.id)"
|
||||
>
|
||||
Confirm
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="step.action === 'element_recovery'" class="recovery-verify">
|
||||
<input
|
||||
v-model="elementRecoveryKey"
|
||||
class="input mono"
|
||||
type="text"
|
||||
placeholder="Paste recovery key (hashed locally)"
|
||||
:disabled="!auth.authenticated || loading || isStepDone(step.id) || isStepBlocked(step.id)"
|
||||
/>
|
||||
<button
|
||||
class="primary verify"
|
||||
type="button"
|
||||
@click="verifyElementRecoveryKey"
|
||||
:disabled="
|
||||
!auth.authenticated ||
|
||||
loading ||
|
||||
isStepDone(step.id) ||
|
||||
isStepBlocked(step.id) ||
|
||||
!elementRecoveryKey.trim()
|
||||
"
|
||||
>
|
||||
Verify
|
||||
</button>
|
||||
<button
|
||||
class="secondary"
|
||||
type="button"
|
||||
@click="confirmStep(step)"
|
||||
:disabled="loading || isStepDone(step.id) || isStepBlocked(step.id) || !elementRecoveryKey.trim()"
|
||||
>
|
||||
Confirm
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<details v-if="step.guide" class="guide-details">
|
||||
<summary class="mono">Photo guide</summary>
|
||||
<div v-if="guideGroups(step).length" class="guide-groups">
|
||||
@ -302,14 +233,63 @@
|
||||
<p v-else class="muted">Guide coming soon.</p>
|
||||
</details>
|
||||
|
||||
<div v-if="step.action === 'checkbox'" class="step-actions">
|
||||
<div v-if="step.action === 'element_recovery'" class="recovery-verify">
|
||||
<input
|
||||
v-model="elementRecoveryKey"
|
||||
class="input mono"
|
||||
type="text"
|
||||
placeholder="Paste recovery key (hashed locally)"
|
||||
:disabled="!auth.authenticated || loading || isStepDone(step.id) || isStepBlocked(step.id)"
|
||||
/>
|
||||
<button
|
||||
class="primary verify"
|
||||
type="button"
|
||||
@click="verifyElementRecoveryKey"
|
||||
:disabled="
|
||||
!auth.authenticated ||
|
||||
loading ||
|
||||
isStepDone(step.id) ||
|
||||
isStepBlocked(step.id) ||
|
||||
!elementRecoveryKey.trim()
|
||||
"
|
||||
>
|
||||
Verify
|
||||
</button>
|
||||
<button
|
||||
class="secondary"
|
||||
type="button"
|
||||
@click="confirmStep(step)"
|
||||
:disabled="loading || isStepDone(step.id) || isStepBlocked(step.id)"
|
||||
:disabled="loading || isStepDone(step.id) || isStepBlocked(step.id) || !elementRecoveryKey.trim()"
|
||||
>
|
||||
Confirm
|
||||
{{ confirmLabel(step) }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else class="step-actions">
|
||||
<template v-if="step.action === 'keycloak_rotate'">
|
||||
<button
|
||||
class="secondary"
|
||||
type="button"
|
||||
@click="requestKeycloakPasswordRotation"
|
||||
:disabled="
|
||||
!auth.authenticated ||
|
||||
loading ||
|
||||
isStepDone('keycloak_password_rotated') ||
|
||||
isStepBlocked('keycloak_password_rotated') ||
|
||||
keycloakPasswordRotationRequested
|
||||
"
|
||||
>
|
||||
Start Keycloak update
|
||||
</button>
|
||||
<a class="mono" href="https://live.bstein.dev" target="_blank" rel="noreferrer">Open Element</a>
|
||||
</template>
|
||||
<button
|
||||
class="secondary"
|
||||
type="button"
|
||||
@click="confirmStep(step)"
|
||||
:disabled="loading || isConfirming(step) || isStepDone(step.id) || isStepBlocked(step.id)"
|
||||
>
|
||||
{{ confirmLabel(step) }}
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
@ -387,6 +367,7 @@ const activeSectionId = ref("vaultwarden");
|
||||
const guideShots = ref({});
|
||||
const guidePage = ref({});
|
||||
const lightboxShot = ref(null);
|
||||
const confirmingStepId = ref("");
|
||||
|
||||
const showPasswordCard = computed(() => Boolean(initialPassword.value || initialPasswordRevealedAt.value));
|
||||
const passwordRevealLocked = computed(() => Boolean(!initialPassword.value && initialPasswordRevealedAt.value));
|
||||
@ -759,6 +740,14 @@ function stepPillClass(step) {
|
||||
return "pill-warn";
|
||||
}
|
||||
|
||||
function isConfirming(step) {
|
||||
return confirmingStepId.value === step.id;
|
||||
}
|
||||
|
||||
function confirmLabel(step) {
|
||||
return isConfirming(step) ? "Confirming..." : "Confirm";
|
||||
}
|
||||
|
||||
function stepCardClass(step) {
|
||||
return {
|
||||
done: isStepDone(step.id),
|
||||
@ -986,19 +975,31 @@ async function setStepCompletion(stepId, completed) {
|
||||
|
||||
async function confirmStep(step) {
|
||||
if (!step || isStepBlocked(step.id) || isStepDone(step.id)) return;
|
||||
if (step.action === "auto") {
|
||||
await check();
|
||||
return;
|
||||
confirmingStepId.value = step.id;
|
||||
try {
|
||||
if (step.action === "auto") {
|
||||
await check();
|
||||
return;
|
||||
}
|
||||
if (step.action === "keycloak_rotate") {
|
||||
await check();
|
||||
return;
|
||||
}
|
||||
if (step.action === "element_recovery") {
|
||||
await verifyElementRecoveryKey();
|
||||
return;
|
||||
}
|
||||
if (step.action === "confirm") {
|
||||
await check();
|
||||
if (!isStepDone(step.id)) {
|
||||
await setStepCompletion(step.id, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
await setStepCompletion(step.id, true);
|
||||
} finally {
|
||||
confirmingStepId.value = "";
|
||||
}
|
||||
if (step.action === "keycloak_rotate") {
|
||||
await requestKeycloakPasswordRotation();
|
||||
return;
|
||||
}
|
||||
if (step.action === "element_recovery") {
|
||||
await verifyElementRecoveryKey();
|
||||
return;
|
||||
}
|
||||
await setStepCompletion(step.id, true);
|
||||
}
|
||||
|
||||
async function verifyElementRecoveryKey() {
|
||||
@ -1454,6 +1455,7 @@ button.copy:disabled {
|
||||
|
||||
.step-card.blocked {
|
||||
opacity: 0.55;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.step-card.done {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user