@escalated-dev/escalated 0.11.2 → 0.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/pages.json +96 -0
- package/src/pages/Auth/TwoFactorChallenge.vue +117 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@escalated-dev/escalated",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.4",
|
|
4
4
|
"description": "Vue 3 + Inertia.js UI components for Escalated — the embeddable support ticket system",
|
|
5
5
|
"author": "Escalated Dev <hello@escalated.dev>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"./pages.json": "./pages.json"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
|
-
"src"
|
|
30
|
+
"src",
|
|
31
|
+
"pages.json"
|
|
31
32
|
],
|
|
32
33
|
"peerDependencies": {
|
|
33
34
|
"@inertiajs/vue3": "^1.0.0 || ^2.0.0 || ^3.0.0",
|
package/pages.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Generated by scripts/generate-page-manifest.js from src/pages. Every name here resolves to a component; a name a backend renders that is not here is a blank screen.",
|
|
3
|
+
"version": "0.11.4",
|
|
4
|
+
"pages": [
|
|
5
|
+
"Escalated/Admin/ApiTokens/Index",
|
|
6
|
+
"Escalated/Admin/AuditLog/Index",
|
|
7
|
+
"Escalated/Admin/Automations/Form",
|
|
8
|
+
"Escalated/Admin/Automations/Index",
|
|
9
|
+
"Escalated/Admin/BusinessHours/Form",
|
|
10
|
+
"Escalated/Admin/BusinessHours/Index",
|
|
11
|
+
"Escalated/Admin/CannedResponses/Index",
|
|
12
|
+
"Escalated/Admin/Capacity/Index",
|
|
13
|
+
"Escalated/Admin/CustomFields/Form",
|
|
14
|
+
"Escalated/Admin/CustomFields/Index",
|
|
15
|
+
"Escalated/Admin/CustomObjects/Form",
|
|
16
|
+
"Escalated/Admin/CustomObjects/Index",
|
|
17
|
+
"Escalated/Admin/CustomObjects/Records",
|
|
18
|
+
"Escalated/Admin/Departments/Form",
|
|
19
|
+
"Escalated/Admin/Departments/Index",
|
|
20
|
+
"Escalated/Admin/EscalationRules/Form",
|
|
21
|
+
"Escalated/Admin/EscalationRules/Index",
|
|
22
|
+
"Escalated/Admin/Import/Connect",
|
|
23
|
+
"Escalated/Admin/Import/Index",
|
|
24
|
+
"Escalated/Admin/Import/Mapping",
|
|
25
|
+
"Escalated/Admin/Import/Progress",
|
|
26
|
+
"Escalated/Admin/Import/Review",
|
|
27
|
+
"Escalated/Admin/KnowledgeBase/Articles/Form",
|
|
28
|
+
"Escalated/Admin/KnowledgeBase/Articles/Index",
|
|
29
|
+
"Escalated/Admin/KnowledgeBase/Categories/Index",
|
|
30
|
+
"Escalated/Admin/Macros/Index",
|
|
31
|
+
"Escalated/Admin/Newsletters/Compose",
|
|
32
|
+
"Escalated/Admin/Newsletters/Edit",
|
|
33
|
+
"Escalated/Admin/Newsletters/Index",
|
|
34
|
+
"Escalated/Admin/Newsletters/Lists/Create",
|
|
35
|
+
"Escalated/Admin/Newsletters/Lists/Index",
|
|
36
|
+
"Escalated/Admin/Newsletters/Lists/Show",
|
|
37
|
+
"Escalated/Admin/Newsletters/Settings",
|
|
38
|
+
"Escalated/Admin/Newsletters/Show",
|
|
39
|
+
"Escalated/Admin/Newsletters/Templates/Create",
|
|
40
|
+
"Escalated/Admin/Newsletters/Templates/Index",
|
|
41
|
+
"Escalated/Admin/Newsletters/Templates/Show",
|
|
42
|
+
"Escalated/Admin/Plugins/Index",
|
|
43
|
+
"Escalated/Admin/Reports",
|
|
44
|
+
"Escalated/Admin/Reports/AgentDetail",
|
|
45
|
+
"Escalated/Admin/Reports/AgentMetrics",
|
|
46
|
+
"Escalated/Admin/Reports/AgentRanking",
|
|
47
|
+
"Escalated/Admin/Reports/Cohorts",
|
|
48
|
+
"Escalated/Admin/Reports/Comparison",
|
|
49
|
+
"Escalated/Admin/Reports/CsatReport",
|
|
50
|
+
"Escalated/Admin/Reports/Dashboard",
|
|
51
|
+
"Escalated/Admin/Reports/ResolutionTimes",
|
|
52
|
+
"Escalated/Admin/Reports/ResponseTimes",
|
|
53
|
+
"Escalated/Admin/Reports/SlaReport",
|
|
54
|
+
"Escalated/Admin/Reports/SlaTrends",
|
|
55
|
+
"Escalated/Admin/Roles/Form",
|
|
56
|
+
"Escalated/Admin/Roles/Index",
|
|
57
|
+
"Escalated/Admin/Settings",
|
|
58
|
+
"Escalated/Admin/Settings/CsatSettings",
|
|
59
|
+
"Escalated/Admin/Settings/DataRetention",
|
|
60
|
+
"Escalated/Admin/Settings/DatabaseConnection",
|
|
61
|
+
"Escalated/Admin/Settings/EmailSettings",
|
|
62
|
+
"Escalated/Admin/Settings/PublicTickets",
|
|
63
|
+
"Escalated/Admin/Settings/Sandbox",
|
|
64
|
+
"Escalated/Admin/Settings/SsoSettings",
|
|
65
|
+
"Escalated/Admin/Settings/TwoFactor",
|
|
66
|
+
"Escalated/Admin/Skills/Form",
|
|
67
|
+
"Escalated/Admin/Skills/Index",
|
|
68
|
+
"Escalated/Admin/SlaPolicies/Form",
|
|
69
|
+
"Escalated/Admin/SlaPolicies/Index",
|
|
70
|
+
"Escalated/Admin/Statuses/Form",
|
|
71
|
+
"Escalated/Admin/Statuses/Index",
|
|
72
|
+
"Escalated/Admin/Tags/Index",
|
|
73
|
+
"Escalated/Admin/Tickets/Index",
|
|
74
|
+
"Escalated/Admin/Tickets/Show",
|
|
75
|
+
"Escalated/Admin/Users/Index",
|
|
76
|
+
"Escalated/Admin/Webhooks/DeliveryLog",
|
|
77
|
+
"Escalated/Admin/Webhooks/Form",
|
|
78
|
+
"Escalated/Admin/Webhooks/Index",
|
|
79
|
+
"Escalated/Admin/Workflows/Builder",
|
|
80
|
+
"Escalated/Admin/Workflows/Form",
|
|
81
|
+
"Escalated/Admin/Workflows/Index",
|
|
82
|
+
"Escalated/Admin/Workflows/Logs",
|
|
83
|
+
"Escalated/Agent/Dashboard",
|
|
84
|
+
"Escalated/Agent/TicketIndex",
|
|
85
|
+
"Escalated/Agent/TicketShow",
|
|
86
|
+
"Escalated/Auth/TwoFactorChallenge",
|
|
87
|
+
"Escalated/Customer/Create",
|
|
88
|
+
"Escalated/Customer/Index",
|
|
89
|
+
"Escalated/Customer/KnowledgeBase/Article",
|
|
90
|
+
"Escalated/Customer/KnowledgeBase/Index",
|
|
91
|
+
"Escalated/Customer/Show",
|
|
92
|
+
"Escalated/Guest/Create",
|
|
93
|
+
"Escalated/Guest/Show",
|
|
94
|
+
"Escalated/Plugin/Page"
|
|
95
|
+
]
|
|
96
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useForm } from '@inertiajs/vue3';
|
|
3
|
+
import { computed, ref } from 'vue';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The post-login two-factor challenge.
|
|
7
|
+
*
|
|
8
|
+
* A backend renders this after authenticating a password but before letting
|
|
9
|
+
* someone into the panel, so it deliberately does not use EscalatedLayout —
|
|
10
|
+
* that layout is the signed-in chrome, and at this point the sign-in is not
|
|
11
|
+
* finished. Nothing here should suggest access that has not been granted yet.
|
|
12
|
+
*
|
|
13
|
+
* Both a TOTP code and a recovery code post to the same endpoint; the backend
|
|
14
|
+
* reads whichever field arrived.
|
|
15
|
+
*/
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
// The route to post to. A host mounts Escalated under its own prefix, and
|
|
18
|
+
// this page is reached before any layout has resolved one.
|
|
19
|
+
action: { type: String, default: '' },
|
|
20
|
+
error: { type: String, default: '' },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const useRecoveryCode = ref(false);
|
|
24
|
+
|
|
25
|
+
const form = useForm({
|
|
26
|
+
code: '',
|
|
27
|
+
recovery_code: '',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const endpoint = computed(() => props.action || route('escalated.two-factor.verify'));
|
|
31
|
+
|
|
32
|
+
function submit() {
|
|
33
|
+
// Only the field in use is sent, so a blank one cannot be mistaken for an
|
|
34
|
+
// attempt with an empty code.
|
|
35
|
+
form.transform((data) =>
|
|
36
|
+
useRecoveryCode.value ? { recovery_code: data.recovery_code } : { code: data.code },
|
|
37
|
+
).post(endpoint.value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function toggleMode() {
|
|
41
|
+
useRecoveryCode.value = !useRecoveryCode.value;
|
|
42
|
+
form.clearErrors();
|
|
43
|
+
form.code = '';
|
|
44
|
+
form.recovery_code = '';
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<div class="flex min-h-screen items-center justify-center bg-[var(--esc-panel-bg)] px-4">
|
|
50
|
+
<div class="w-full max-w-sm">
|
|
51
|
+
<h1 class="text-lg font-semibold text-[var(--esc-panel-text-secondary)]">Two-factor authentication</h1>
|
|
52
|
+
<p class="mt-1 text-sm text-[var(--esc-panel-text-muted)]">
|
|
53
|
+
{{
|
|
54
|
+
useRecoveryCode
|
|
55
|
+
? 'Enter one of the recovery codes you saved when you set this up.'
|
|
56
|
+
: 'Enter the six-digit code from your authenticator app.'
|
|
57
|
+
}}
|
|
58
|
+
</p>
|
|
59
|
+
|
|
60
|
+
<form
|
|
61
|
+
class="mt-6 rounded-xl border border-[var(--esc-panel-border)] bg-[var(--esc-panel-surface)] p-5"
|
|
62
|
+
@submit.prevent="submit"
|
|
63
|
+
>
|
|
64
|
+
<div v-if="!useRecoveryCode">
|
|
65
|
+
<label class="block text-xs font-medium text-[var(--esc-panel-text-muted)]" for="totp-code">
|
|
66
|
+
Authentication code
|
|
67
|
+
</label>
|
|
68
|
+
<input
|
|
69
|
+
id="totp-code"
|
|
70
|
+
v-model="form.code"
|
|
71
|
+
type="text"
|
|
72
|
+
inputmode="numeric"
|
|
73
|
+
autocomplete="one-time-code"
|
|
74
|
+
maxlength="6"
|
|
75
|
+
autofocus
|
|
76
|
+
class="mt-1 w-full rounded-lg border border-[var(--esc-panel-border)] bg-[var(--esc-panel-bg)] px-3 py-2 text-center text-lg tracking-[0.4em] text-[var(--esc-panel-text-secondary)] focus:border-[var(--esc-panel-accent)] focus:outline-none"
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div v-else>
|
|
81
|
+
<label class="block text-xs font-medium text-[var(--esc-panel-text-muted)]" for="recovery-code">
|
|
82
|
+
Recovery code
|
|
83
|
+
</label>
|
|
84
|
+
<input
|
|
85
|
+
id="recovery-code"
|
|
86
|
+
v-model="form.recovery_code"
|
|
87
|
+
type="text"
|
|
88
|
+
autocomplete="off"
|
|
89
|
+
autofocus
|
|
90
|
+
class="mt-1 w-full rounded-lg border border-[var(--esc-panel-border)] bg-[var(--esc-panel-bg)] px-3 py-2 text-[var(--esc-panel-text-secondary)] focus:border-[var(--esc-panel-accent)] focus:outline-none"
|
|
91
|
+
/>
|
|
92
|
+
<p class="mt-1 text-xs text-[var(--esc-panel-text-muted)]">Each recovery code works once.</p>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<p v-if="error || form.errors.code || form.errors.recovery_code" class="mt-2 text-xs text-red-400">
|
|
96
|
+
{{ error || form.errors.code || form.errors.recovery_code }}
|
|
97
|
+
</p>
|
|
98
|
+
|
|
99
|
+
<button
|
|
100
|
+
type="submit"
|
|
101
|
+
:disabled="form.processing"
|
|
102
|
+
class="mt-4 w-full rounded-lg bg-gradient-to-r from-[var(--esc-panel-accent)] to-[var(--esc-panel-accent-secondary)] px-4 py-2 text-sm font-medium text-white transition-all hover:from-[var(--esc-panel-accent-hover)] hover:to-[var(--esc-panel-accent-secondary-hover)] disabled:opacity-50"
|
|
103
|
+
>
|
|
104
|
+
Verify
|
|
105
|
+
</button>
|
|
106
|
+
|
|
107
|
+
<button
|
|
108
|
+
type="button"
|
|
109
|
+
class="mt-3 w-full text-xs text-[var(--esc-panel-text-muted)] transition-colors hover:text-[var(--esc-panel-text-secondary)]"
|
|
110
|
+
@click="toggleMode"
|
|
111
|
+
>
|
|
112
|
+
{{ useRecoveryCode ? 'Use an authenticator code instead' : 'Use a recovery code instead' }}
|
|
113
|
+
</button>
|
|
114
|
+
</form>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</template>
|