@adminforth/two-factors-auth 3.1.5 → 3.2.1

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/build.log CHANGED
@@ -16,5 +16,5 @@ custom/pnpm-lock.yaml
16
16
  custom/tsconfig.json
17
17
  custom/utils.js
18
18
 
19
- sent 283,900 bytes received 229 bytes 568,258.00 bytes/sec
20
- total size is 282,994 speedup is 1.00
19
+ sent 285,197 bytes received 229 bytes 570,852.00 bytes/sec
20
+ total size is 284,303 speedup is 1.00
@@ -1,46 +1,53 @@
1
1
  <template>
2
2
  <div class="af-two-factors-modal fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 top-0 bottom-0 left-0 right-0"
3
3
  v-show ="modelShow && (isLoading === false)">
4
- <div v-if="modalMode === 'totp'" class="af-two-factor-modal-totp flex flex-col items-center relative bg-white dark:bg-gray-700 rounded-lg shadow p-6 w-full max-w-md">
5
- <div id="mfaCode-label" class="mb-4 text-gray-700 dark:text-gray-100 text-center">
6
- <p> {{ customDialogTitle }} </p>
7
- <p class="text-red-500 font-semibold text-xl" v-if="sessionsIdsToResolve.length > 1"> You are confirming {{ sessionsIdsToResolve.length }} actions</p>
8
- <p>{{ $t('Please enter your authenticator code') }}</p>
9
- </div>
10
-
11
- <div class="flex flex-col max-w-[calc(15rem_+_60px)]">
12
- <div class="mb-4 w-full flex justify-center" ref="otpRoot">
13
- <v-otp-input
14
- ref="confirmationResult"
15
- container-class="grid grid-cols-6 gap-3 w-full"
16
- input-classes="bg-gray-50 text-center flex justify-center otp-input border leading-none border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-10 h-10 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
17
- :num-inputs="6"
18
- inputType="number"
19
- inputmode="numeric"
20
- :should-auto-focus="true"
21
- :should-focus-order="true"
22
- v-model:value="bindValue"
23
- @on-complete="handleOnComplete"
24
- />
4
+ <div v-if="modalMode === 'totp'" class="af-two-factor-modal-totp flex flex-col gap-4 relative bg-white dark:bg-gray-700 rounded-lg shadow p-6 w-full max-w-md">
5
+ <button
6
+ type="button"
7
+ class="af-2fa-close-btn text-lightDialogCloseButton bg-transparent hover:bg-lightDialogCloseButtonHoverBackground hover:text-lightDialogCloseButtonHover rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:text-darkDialogCloseButton dark:hover:bg-darkDialogCloseButtonHoverBackground dark:hover:text-darkDialogCloseButtonHover"
8
+ @click="onCancel"
9
+ >
10
+ <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
11
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
12
+ </svg>
13
+ <span class="sr-only">{{$t('Close modal')}}</span>
14
+ </button>
15
+
16
+ <div class="af-2fa-totp-header flex flex-col items-center justify-center gap-3">
17
+ <div class="af-2fa-icon-wrap w-14 h-14 shrink-0 flex items-center justify-center rounded-full bg-lightPrimary dark:bg-darkPrimary">
18
+ <IconShieldOutline class="af-2fa-shield-icon w-7 h-7 text-white" />
25
19
  </div>
26
-
27
- <div class="flex items-center w-full" :class="doesUserHavePasskeys ? 'justify-between' : 'justify-center' ">
28
- <p v-if="doesUserHavePasskeys===true" class="underline hover:no-underline text-lightPrimary whitespace-nowrap hover:cursor-pointer" @click="modalMode = 'passkey'" >{{$t('use passkey')}}</p>
29
- <Button
30
- class="px-4 py-2 rounded border"
31
- @click="onCancel"
32
- :disabled="inProgress"
33
- >{{ $t('Cancel') }}</Button>
20
+ <div id="mfaCode-label" class="af-2fa-totp-title-wrap">
21
+ <p v-if="customDialogTitle" class="af-2fa-custom-title text-xl text-center font-medium text-gray-900 dark:text-white">{{ customDialogTitle }}</p>
22
+ <p class="af-2fa-totp-subtitle text-xs text-center text-gray-500 dark:text-gray-400 mt-1">{{ $t('Please enter your authenticator code') }}</p>
34
23
  </div>
35
24
  </div>
36
- </div>
37
-
38
25
 
26
+ <div class="af-2fa-otp-root flex justify-center" ref="otpRoot">
27
+ <v-otp-input
28
+ ref="confirmationResult"
29
+ container-class="grid grid-cols-6 gap-3"
30
+ input-classes="bg-gray-50 text-center flex justify-center otp-input border leading-none border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-10 h-10 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
31
+ :num-inputs="6"
32
+ inputType="number"
33
+ inputmode="numeric"
34
+ :should-auto-focus="true"
35
+ :should-focus-order="true"
36
+ v-model:value="bindValue"
37
+ @on-complete="handleOnComplete"
38
+ />
39
+ </div>
40
+ <p v-if="doesUserHavePasskeys" class="af-2fa-totp-footer text-center text-xs text-gray-500 dark:text-gray-400">
41
+ {{$t('Having trouble?')}}
42
+ <button type="button" class="af-2fa-switch-to-passkey text-lightPrimary dark:text-white hover:underline cursor-pointer" @click="modalMode = 'passkey'">{{$t('Use passkey instead')}}</button>
43
+ </p>
44
+ <p class="af-2fa-multiple-actions text-center text-red-500 text-xs" v-if="sessionsIdsToResolve.length > 1"> You are confirming {{ sessionsIdsToResolve.length }} actions</p>
45
+ </div>
39
46
 
40
- <div v-else-if="modalMode === 'passkey'" class="af-two-factor-modal-passkeys flex flex-col items-center justify-center py-4 gap-6 relative bg-white dark:bg-gray-700 rounded-lg shadow p-6">
47
+ <div v-else-if="modalMode === 'passkey'" class="af-two-factor-modal-passkeys flex flex-col gap-4 relative bg-white dark:bg-gray-700 rounded-lg shadow p-6 w-full max-w-md">
41
48
  <button
42
49
  type="button"
43
- class="text-lightDialogCloseButton bg-transparent hover:bg-lightDialogCloseButtonHoverBackground hover:text-lightDialogCloseButtonHover rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:text-darkDialogCloseButton dark:hover:bg-darkDialogCloseButtonHoverBackground dark:hover:text-darkDialogCloseButtonHover"
50
+ class="af-2fa-close-btn text-lightDialogCloseButton bg-transparent hover:bg-lightDialogCloseButtonHoverBackground hover:text-lightDialogCloseButtonHover rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:text-darkDialogCloseButton dark:hover:bg-darkDialogCloseButtonHoverBackground dark:hover:text-darkDialogCloseButtonHover"
44
51
  @click="onCancel"
45
52
  >
46
53
  <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
@@ -48,25 +55,41 @@
48
55
  </svg>
49
56
  <span class="sr-only">{{$t('Close modal')}}</span>
50
57
  </button>
51
- <IconShieldOutline class="af-2fa-shield-icon w-16 h-16 text-lightPrimary dark:text-darkPrimary"/>
52
- <p class="text-4xl font-semibold mb-4 text:gray-900 dark:text-gray-200 ">{{$t('Passkey')}}</p>
53
- <div class="mb-2 max-w-[300px] text:gray-900 dark:text-gray-200">
54
- <p class="mb-2">{{customDialogTitle}} </p>
55
- <p class="text-red-500 font-semibold text-xl text-center mb-12" v-if="sessionsIdsToResolve.length > 1"> You are confirming {{ sessionsIdsToResolve.length }} actions</p>
56
- <p>{{$t('Authenticate yourself using the button below')}}</p>
57
- </div>
58
- <Button @click="usePasskeyButtonClick" :disabled="isFetchingPasskey" :loader="isFetchingPasskey" class="w-full mx-16">
59
- {{$t('Use passkey')}}
60
- </Button>
61
- <div v-if="modalMode === 'passkey'" class="af-2fa-passkey-issues-card max-w-sm px-6 pt-3 w-full bg-white border border-gray-200 rounded-lg shadow-sm dark:bg-gray-800 dark:border-gray-700">
62
- <div class="mb-3 font-normal text-gray-700 dark:text-gray-400">
63
- <p>{{$t('Have issues with passkey?')}}</p>
64
- <p class="underline hover:no-underline text-lightPrimary whitespace-nowrap hover:cursor-pointer" @click="modalMode = 'totp'" >{{$t('use TOTP')}}</p>
58
+
59
+ <div class="af-2fa-passkey-header flex flex-col items-center justify-center gap-3">
60
+ <div class="af-2fa-icon-wrap w-14 h-14 shrink-0 flex items-center justify-center rounded-full bg-lightPrimary dark:bg-darkPrimary">
61
+ <IconShieldOutline class="af-2fa-shield-icon w-7 h-7 text-white" />
62
+ </div>
63
+ <div class="af-2fa-passkey-title-wrap">
64
+ <p class="af-2fa-passkey-title text-xl text-center font-medium text-gray-900 dark:text-white">{{$t('Verify to add passkey')}}</p>
65
+ <p class="af-2fa-passkey-subtitle text-xs text-center text-gray-500 dark:text-gray-400 mt-1">{{$t("Confirm it's you before registering a new passkey on this device.")}}</p>
65
66
  </div>
66
67
  </div>
67
68
 
69
+ <div class="af-2fa-passkey-steps flex flex-col gap-2 mt-2">
70
+ <div
71
+ v-for="(step, i) in [
72
+ $t('Click the button below to begin'),
73
+ $t('Authenticate with your device biometrics or PIN'),
74
+ $t('Your passkey will be saved automatically'),
75
+ ]"
76
+ :key="i"
77
+ class="af-2fa-passkey-step flex items-center gap-2.5 px-3 py-2 rounded-lg bg-gray-50 dark:bg-gray-600/50 text-xs text-gray-600 dark:text-gray-300"
78
+ >
79
+ <span class="af-2fa-step-number shrink-0 w-5 h-5 flex items-center justify-center rounded-full bg-lightPrimary dark:bg-darkPrimary text-white font-semibold text-xs">{{ i + 1 }}</span>
80
+ {{ step }}
81
+ </div>
82
+ </div>
68
83
 
69
-
84
+ <Button @click="usePasskeyButtonClick" :disabled="isFetchingPasskey" :loader="isFetchingPasskey" class="af-2fa-passkey-btn w-full flex items-center justify-center gap-2 mt-2">
85
+ <IconShieldOutline class="w-4 h-4" />
86
+ {{$t('Use passkey to verify')}}
87
+ </Button>
88
+ <p class="af-2fa-passkey-footer text-center text-xs text-gray-500 dark:text-gray-400">
89
+ {{$t('Having trouble?')}}
90
+ <button type="button" class="af-2fa-switch-to-totp text-lightPrimary dark:text-white hover:underline cursor-pointer" @click="modalMode = 'totp'">{{$t('Use TOTP instead')}}</button>
91
+ </p>
92
+ <p class="af-2fa-multiple-actions text-center text-red-500 text-xs" v-if="sessionsIdsToResolve.length > 1"> You are confirming {{ sessionsIdsToResolve.length }} actions</p>
70
93
  </div>
71
94
  </div>
72
95
  </template>
@@ -85,13 +108,15 @@
85
108
  import websocket from '@/websocket';
86
109
  import type { AdminUser } from '@/types/Common';
87
110
 
111
+ type TwoFaConfirmationResult = { mode: 'totp'; result: string } | { mode: 'passkey'; result: Record<string, any> };
112
+
88
113
  declare global {
89
114
  interface Window {
90
115
  adminforthTwoFaModal: {
91
116
  get2FaConfirmationResult: (
92
117
  title?: string,
93
118
  verifyingCallback?: (confirmationResult: string) => Promise<boolean>
94
- ) => Promise<any>;
119
+ ) => Promise<TwoFaConfirmationResult>;
95
120
  };
96
121
  }
97
122
  }